Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为SIGFPE设置标志并忽略FPE继续执行_C_Linux_Floating Point_Signals - Fatal编程技术网

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

C 为SIGFPE设置标志并忽略FPE继续执行,c,linux,floating-point,signals,C,Linux,Floating Point,Signals,在数值应用程序中,我想知道计算完成后是否发生浮点异常。默认情况下,浮点除法和无效操作将被默认忽略 我的尝试是启用我关心的FPE,通过设置标志并再次禁用它们来处理SIGFPE,以允许继续执行: #include <fenv.h> #include <signal.h> #include <stdio.h> int caught = 0; struct sigaction old_sa; /* (2) */ fenv_t fenv_hold; void sig

在数值应用程序中,我想知道计算完成后是否发生浮点异常。默认情况下,浮点除法和无效操作将被默认忽略

我的尝试是启用我关心的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");
}
预期产出:

Dividing by zero..
Caught in handler, disabling
Continuing

如果您只是想知道,在计算完成后,是否发生了浮点异常,那么您不应该使用信号,因为它们有很高的开销。相反,使用浮点异常标志,处理器在正常执行期间快速设置这些标志

请参见
上的C标准。简而言之:

  • 在源文件中插入
    #包括
  • 在可能访问浮点标志或在非默认浮点模式下运行的任何源代码之前插入
    #pragma STDC FENV_ACCESS on
  • 如果需要,请在上述源代码之后插入
    #pragma STDC FENV_ACCESS off
    ,此时以下源代码无法访问标志或在非默认模式下运行
  • 在计算之前,执行
    feclearException(FE\u ALL\u EXCEPT)
    清除标志
  • 计算完成后,执行
    fetestexcept(异常)
    以测试标志<代码>异常
    应为按位或的
    FE\u除以零
    FE\u不精确
    FE\u无效
    FE\u溢出
    ,和/或
    FE\u下溢
    ,可能还有其他实现定义的标志

请注意,某些C实现对访问浮点环境的支持较差。

1的可能重复项)
void sighandler()
应该是
void sighandler(int signum)
2)您不应该从信号处理程序中调用printf。谢谢您的评论,我知道。此代码仅用于演示。如果实现的支持较差,则使用信号处理程序不会更好。支持方面的问题是,编译器可能会进行无效的优化,从而导致在抽象机器上发生不同的异常。
Dividing by zero..
Caught in handler, disabling
Continuing