首页 > 解决方案 > 处理除以零导致意外行为

问题描述

我试图处理整数除以零(请不要判断,我被告知我必须使用<csignal>lib 并且我不能只使用 if 语句),但我需要确保程序能够继续运行(即使虽然这是一个非常糟糕的做法),而不是崩溃或关闭。奇怪的部分是程序应该只处理被零除,但应该退出所有其他类型的SIGFPE.

旁注:现在,我不知道他们为什么使用类似FPUor的名称,FE或者FPE在引用整数“异常”(或者我应该说中断)时,因为标准明确规定除以浮点数应该返回或者返回infnan告诉0 / 0我如果我'我错了)。

无论如何,我编写了这个测试代码,以便更好地理解在实际实施之前我需要做什么。我知道,拥有一个全局变量很奇怪,x但如果我不重置它,它会handle像永远一样无缘无故地继续调用......

#include <iostream>
#include <csignal>

using namespace std;

int x = 0;

void handle(int s);

int main(int argc, char * argv[]) {
    signal(SIGFPE, handle);
    cout << "Insert 0: ";
    cin >> x; // here I would input 0, so the program can compile
    x = 5 / x;
    cout << "X: " << x << endl;
    return 0;
}

void handle(int s) {
    if (s != FPE_INTDIV) exit(1);
    cout << "sig: " << s << endl;
    x = 1;
}

如您所见,我过去常常FPE_INTDIV排除所有其他类型的例外,但它不起作用。最终我发现这FPE_INTDIV是一个符号常量7(这就是 vs-code 的智能感知告诉我的),如果我要打印 的值s,那就是8. 我发现,奇怪的8是,FPE_INTOVF文档声明它是专门为整数溢出设计的值。

如果整数除法有符号,为什么溢出的符号值用于整数除法?我错过了什么?有人弄乱了图书馆的价值观吗?我使用了错误的宏吗?

我还应该提到,这段代码可以用clang++g++很好地编译,但是当在 Windows 计算机上用cl编译时,它告诉我没有FPE_INTDIV.

我如何确定自己在做什么并编写一个有效的跨平台解决方案?

我已经觉得自己像个白痴了。

标签: c++signalsdivide-by-zero

解决方案


定义为:

SIGFPE信号报告一个致命的算术错误。虽然名称来源于“浮点异常”,但这个信号实际上涵盖了所有算术错误,包括被零除和溢出。如果程序将整数数据存储在一个位置,然后用于浮点运算,这通常会导致“无效运算”异常,因为处理器无法将数据识别为浮点数。

没有理由对其进行专门标记FPE,但这些标签可能会以不可预知的方式演变。我不会读太多。

这些信号是 POSIX 标准的一部分,在 Windows 中可能不完全支持或实现。这些支持工具的 Windows 实现在许多方面都缺乏,例如如何fork()不受支持。


推荐阅读