简体   繁体   English

为SIGFPE设置标志并继续执行忽略FPE

[英]Set flag for SIGFPE and continue execution ignoring FPEs

In a numerical application, I'd like to know if a floating point exception occured after the computation finishes. 在数值应用程序中,我想知道计算完成后是否发生浮点异常。 By default, floating point divisions and invalid operations are ignored silently. 默认情况下,将以静默方式忽略浮点除法和无效操作。

My attempt is to enable FPEs I care about, handle SIGFPE by setting a flag and disabling them again to allow execution to continue: 我的尝试是启用我关心的FPE,通过设置标志来处理SIGFPE并再次禁用它们以允许继续执行:

#include <fenv.h>
#include <signal.h>
#include <stdio.h>

int caught = 0;
struct sigaction old_sa;
/* (2) */ fenv_t fenv_hold;

void sighandler()
{
    caught = 1;
    printf("Caught in handler, disabling\n");
    /* (1) */ fedisableexcept(FE_ALL_EXCEPT);
    /* (2) */ feholdexcept(&fenv_hold);
    sigaction(SIGFPE, &old_sa, NULL);
}

int main(void)
{
    struct sigaction sa;
    volatile double a=1, b=0;

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = sighandler;
    sigaction(SIGFPE, &sa, &old_sa);

    feenableexcept(FE_DIVBYZERO);
    printf("Dividing by zero..\n");
    a/=b;
    printf("Continuing\n");
}

I took two approaches, the first one labeled with (1) , the second one with (2) . 我采用了两种方法,第一种用(1)标记,第二种用(2)标记。 Neither of them works as expected. 它们都没有按预期工作。

Output: 输出:

Dividing by zero..
Caught in handler, disabling
Floating point exception (core dumped)

Expected Output: 预期产出:

Dividing by zero..
Caught in handler, disabling
Continuing

If you just want to know, after a computation finishes, whether a floating-point exception occurred, then you should not use signals, as they have a high overhead. 如果您只是想知道,在计算完成后,是否发生了浮点异常,那么您不应该使用信号,因为它们的开销很高。 Instead, use the floating-point exception flags, which are set quickly by the processor during normal execution. 而是使用浮点异常标志,这些标志在正常执行期间由处理器快速设置。

See the C standard on <fenv.h> . 请参阅<fenv.h>上的C标准。 Briefly: 简述:

  • Insert #include <fenv.h> in your source file. 在源文件中插入#include <fenv.h>
  • Insert #pragma STDC FENV_ACCESS on before any source code that might access the floating-point flags or run under non-default floating-point modes. 在任何可能访问浮点标志或在非默认浮点模式下运行的源代码之前插入#pragma STDC FENV_ACCESS on
  • If desired, insert #pragma STDC FENV_ACCESS off after the above source code, when the following source code does not access the flags or run under non-default modes. 如果需要,请在上述源代码之后插入#pragma STDC FENV_ACCESS off ,此时以下源代码不访问标志或在非默认模式下运行。
  • Before a computation, execute feclearexcept(FE_ALL_EXCEPT) to clear flags. 在计算之前,执行feclearexcept(FE_ALL_EXCEPT)以清除标志。
  • After a computation, execute fetestexcept(exceptions) to test flags. 计算完成后,执行fetestexcept(exceptions)来测试标志。 exceptions should be a bitwise OR of FE_DIVBYZERO , FE_INEXACT , FE_INVALID , FE_OVERFLOW , and/or FE_UNDERFLOW , and possibly additional implementation-defined flags. exceptions应该是一个按位或的FE_DIVBYZEROFE_INEXACTFE_INVALIDFE_OVERFLOW ,和/或FE_UNDERFLOW ,以及可能的附加实现定义的标志。

Note that some C implementations have poor support for accessing the floating-point environment. 请注意,某些C实现对访问浮点环境的支持较差。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM