【问题标题】:Can I make gcc tell me when a calculation results in NaN or inf at runtime?我可以让 gcc 在运行时告诉我计算结果是 NaN 还是 inf 吗?
【发布时间】:2023-03-11 05:00:01
【问题描述】:

有没有办法告诉 gcc 抛出一个 SIGFPE 或类似的东西来响应在运行时导致 NaN(-)inf 的计算,就像除以零一样?

我尝试了-fsignaling-nans 标志,但似乎没有帮助。

【问题讨论】:

  • -fsignaling-nans 是运行时,而不是编译时。

标签: c gcc floating-point


【解决方案1】:

几乎任何从非 NaN 输入产生 NaN 的浮点运算或数学库函数也应该发出“无效运算”浮点异常的信号;同样,从有限输入产生无穷大的计算通常会发出“被零除”或“溢出”浮点异常的信号。因此,您需要某种方式将这些异常转换为 SIGFPE。

我怀疑答案将高度依赖于系统,因为浮点陷阱和标志的控制可能由平台 C 库而不是 gcc 本身提供。但这是一个适用于我的例子,在 Linux 上。它使用来自fenv.hfeenableexcept 函数。要声明此函数,_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)来触发异常。

【讨论】:

    【解决方案2】:

    在 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
    }
    

    【讨论】:

    • 这似乎不适用于 MinGW 4.6.2('_clearfp()' 未在此范围内声明)
    猜你喜欢
    • 2011-03-30
    • 2011-05-01
    • 2013-12-25
    • 1970-01-01
    • 2011-03-15
    • 2020-04-30
    • 2015-06-19
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多