对不起,真正的答案是在底部。
浮点异常由C99库代码控制,而不是由编译器标志控制。下面是一个例子:
#include< fenv.h> #include< math.h> #include< stdio.h> $ b #define PRINTEXC(ex,val)printf(#ex:%s \ n,(val& ex)?set:unset); double foo(double a,double b){return sin(a)/ b; } int main() { int e; double x; feclearexcept(FE_ALL_EXCEPT); x = foo(1.2,3.1); e = fetestexcept(FE_ALL_EXCEPT); PRINTEXC(FE_DIVBYZERO,e); PRINTEXC(FE_INEXACT,e); PRINTEXC(FE_INVALID,e); PRINTEXC(FE_OVERFLOW,e); PRINTEXC(FE_UNDERFLOW,e); putchar('\\\'); feclearexcept(FE_ALL_EXCEPT); x + = foo(1.2,0.0); e = fetestexcept(FE_ALL_EXCEPT); PRINTEXC(FE_DIVBYZERO,e); PRINTEXC(FE_INEXACT,e); PRINTEXC(FE_INVALID,e); PRINTEXC(FE_OVERFLOW,e); PRINTEXC(FE_UNDERFLOW,e); return lrint(x); $ / code $ / pre $ b $输出: FE_DIVBYZERO:取消设置 FE_INEXACT:设置 FE_INVALID:取消设置 FE_OVERFLOW:取消设置 FE_UNDERFLOW:取消设置 FE_DIVBYZERO:set FE_INEXACT:set FE_INVALID:unset FE_OVERFLOW:未设定 FE_UNDERFLOW:未设定 更新:使用GNU GCC,您可能会导致浮点异常陷阱和发送信号:pre#pragma STDC FENV_ACCESS on #define _GNU_SOURCE #include
Gfortran has the handy -ffpe-trap compiler option, but no similar option is available for gcc. I am vaguely aware that they handle exceptions differently, but not enough to know why one can die from FPEs just by enabling a compiler flag, but the other requires including extra code to turn exceptions on.
解决方案Sorry for the wall of text; the real answer is at the bottom.
Floating point exceptions are controlled by library code in C99, not by compiler flags. Here's an example:
#include <fenv.h> #include <math.h> #include <stdio.h> #define PRINTEXC(ex, val) printf(#ex ": %s\n", (val & ex) ? "set" : "unset"); double foo(double a, double b) { return sin(a) / b; } int main() { int e; double x; feclearexcept(FE_ALL_EXCEPT); x = foo(1.2, 3.1); e = fetestexcept(FE_ALL_EXCEPT); PRINTEXC(FE_DIVBYZERO, e); PRINTEXC(FE_INEXACT, e); PRINTEXC(FE_INVALID, e); PRINTEXC(FE_OVERFLOW, e); PRINTEXC(FE_UNDERFLOW, e); putchar('\n'); feclearexcept(FE_ALL_EXCEPT); x += foo(1.2, 0.0); e = fetestexcept(FE_ALL_EXCEPT); PRINTEXC(FE_DIVBYZERO, e); PRINTEXC(FE_INEXACT, e); PRINTEXC(FE_INVALID, e); PRINTEXC(FE_OVERFLOW, e); PRINTEXC(FE_UNDERFLOW, e); return lrint(x); }Output:
FE_DIVBYZERO: unset FE_INEXACT: set FE_INVALID: unset FE_OVERFLOW: unset FE_UNDERFLOW: unset FE_DIVBYZERO: set FE_INEXACT: set FE_INVALID: unset FE_OVERFLOW: unset FE_UNDERFLOW: unset
Update: With GNU GCC, you may be able to alternatively cause floating point exceptions to trap and send a signal:
#pragma STDC FENV_ACCESS on #define _GNU_SOURCE #include <fenv.h> int main() { #ifdef FE_NOMASK_ENV fesetenv(FE_NOMASK_ENV); #endif // ... }However, it's not entirely clear what you should do when you receive a SIGFPE, since you can't undo the faulty instruction. (And see @EricPostpischil's comments about the pragma; thanks!)
更多推荐
使用C编译器选项捕捉浮点异常
发布评论