【发布时间】:2023-03-11 05:00:01
【问题描述】:
有没有办法告诉 gcc 抛出一个 SIGFPE 或类似的东西来响应在运行时导致 NaN 或 (-)inf 的计算,就像除以零一样?
我尝试了-fsignaling-nans 标志,但似乎没有帮助。
【问题讨论】:
-
-fsignaling-nans是运行时,而不是编译时。
标签: c gcc floating-point
有没有办法告诉 gcc 抛出一个 SIGFPE 或类似的东西来响应在运行时导致 NaN 或 (-)inf 的计算,就像除以零一样?
我尝试了-fsignaling-nans 标志,但似乎没有帮助。
【问题讨论】:
-fsignaling-nans 是运行时,而不是编译时。
标签: c gcc floating-point
几乎任何从非 NaN 输入产生 NaN 的浮点运算或数学库函数也应该发出“无效运算”浮点异常的信号;同样,从有限输入产生无穷大的计算通常会发出“被零除”或“溢出”浮点异常的信号。因此,您需要某种方式将这些异常转换为 SIGFPE。
我怀疑答案将高度依赖于系统,因为浮点陷阱和标志的控制可能由平台 C 库而不是 gcc 本身提供。但这是一个适用于我的例子,在 Linux 上。它使用来自fenv.h 的feenableexcept 函数。要声明此函数,_GNU_SOURCE 定义是必需的。
#define _GNU_SOURCE
#include <fenv.h>
int main(void) {
double x, y, z;
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
x = 1e300;
y = 1e300;
z = x * y; /* should cause an FPE */
return 0;
}
一个警告:我认为在某些设置中,可能直到 next 浮点操作之后才真正生成异常(理论上)应该导致它,所以你有时需要无操作浮点运算(例如乘以 1.0)来触发异常。
【讨论】:
在 MinGW 4.8.1(Win32 的 GCC)上,我看到 feenableexcept 没有定义。解决方法是使用 Win32 平台的_controlfp,因此:
#undef __STRICT_ANSI__ // _controlfp is a non-standard function documented in MSDN
#include <float.h>
#include <stdio.h>
int main()
{
_clearfp();
unsigned unused_current_word = 0;
// clearing the bits unmasks (throws) the exception
_controlfp_s(&unused_current_word, 0, _EM_OVERFLOW | _EM_ZERODIVIDE); // _controlfp_s is the secure version of _controlfp
float num = 1.0f, den = 0.0f;
float quo = num / den;
printf("%.8f\n", quo); // the control should never reach here, due to the exception thrown above
}
【讨论】: