使用 <csignal> 处理除以零会导致意外行为
Handling division by zero with <csignal> results in unexpected behaviour
我试图处理整数除以零(请不要判断,我被告知我必须使用 <csignal>
库,我不能只使用 if 语句),但我需要确保程序将保持 运行(即使这是一个非常糟糕的做法),而不是崩溃或关闭。奇怪的是程序应该只处理除以零但应该退出所有其他类型的 SIGFPE
.
旁注:现在,我不知道为什么他们在引用整数时使用 FPU
或 FE
或 FPE
这样的名称 "exceptions"(或者我应该说中断),因为标准明确表示除法浮点数应该 return inf
或 nan
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
.
没有宏
我如何确定自己在做什么并编写有效的跨平台解决方案?
我已经觉得自己像个白痴了。
defined 为:
The SIGFPE
signal reports a fatal arithmetic error. Although the name is derived from “floating-point exception”, this signal actually covers all arithmetic errors, including division by zero and overflow. If a program stores integer data in a location which is then used in a floating-point operation, this often causes an “invalid operation” exception, because the processor cannot recognize the data as a floating-point number.
没有理由专门为它贴上标签FPE
,但这类标签可能会以不可预测的方式演变。我不会读太多。
这些 signals 是 POSIX 标准的一部分,可能未在 Windows 中得到完全支持或实施。 Windows 这些支持设施的实施在许多领域都缺乏,例如如何 fork()
不受支持。
我试图处理整数除以零(请不要判断,我被告知我必须使用 <csignal>
库,我不能只使用 if 语句),但我需要确保程序将保持 运行(即使这是一个非常糟糕的做法),而不是崩溃或关闭。奇怪的是程序应该只处理除以零但应该退出所有其他类型的 SIGFPE
.
旁注:现在,我不知道为什么他们在引用整数时使用 FPU
或 FE
或 FPE
这样的名称 "exceptions"(或者我应该说中断),因为标准明确表示除法浮点数应该 return inf
或 nan
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
.
我如何确定自己在做什么并编写有效的跨平台解决方案?
我已经觉得自己像个白痴了。
defined 为:
The
SIGFPE
signal reports a fatal arithmetic error. Although the name is derived from “floating-point exception”, this signal actually covers all arithmetic errors, including division by zero and overflow. If a program stores integer data in a location which is then used in a floating-point operation, this often causes an “invalid operation” exception, because the processor cannot recognize the data as a floating-point number.
没有理由专门为它贴上标签FPE
,但这类标签可能会以不可预测的方式演变。我不会读太多。
这些 signals 是 POSIX 标准的一部分,可能未在 Windows 中得到完全支持或实施。 Windows 这些支持设施的实施在许多领域都缺乏,例如如何 fork()
不受支持。