C 为SIGFPE设置标志并忽略FPE继续执行
在数值应用程序中,我想知道计算完成后是否发生浮点异常。默认情况下,浮点除法和无效操作将被默认忽略 我的尝试是启用我关心的FPE,通过设置标志并再次禁用它们来处理SIGFPE,以允许继续执行: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
#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