使用C编译器选项捕捉浮点异常

编程入门 行业动态 更新时间:2024-10-27 00:25:22
本文介绍了使用C编译器选项捕捉浮点异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 Gfortran 具有方便的 -ffpe-trap 编译器选项,但是没有类似的选项可用于 gcc 。我隐约地意识到,他们处理异常的方式不同,但不足以知道为什么只能通过启用编译器标志才能从 FPEs 死亡,而另一个则需要包含额外的代码才能打开异常。

解决方案

对不起,真正的答案是在底部。

浮点异常由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 然而,当你收到一个SIGFPE时,你不应该做什么,因为你不能撤销错误的指令。 (请参阅@ EricPostpischil关于该附注的评论,谢谢!)

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编译器选项捕捉浮点异常

本文发布于:2023-11-10 06:40:17,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:浮点   编译器   选项   异常

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!