【问题标题】:Division by zero does not throw SIGFPE除以零不会抛出 SIGFPE
【发布时间】:2011-11-08 05:33:02
【问题描述】:

我有一个小程序执行浮点除以零,所以我期待 SIGFPE。

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

void signal_handler (int signo) {
    if(signo == SIGFPE) {
      std::cout << "Caught FPE\n";
    }
}

int main (void) {
  signal(SIGFPE,(*signal_handler));

  double b = 1.0;
  double c = 0.0;
  double d = b/c;
  std::cout << "d = "<< d << std::endl;
  return 0;
}

其实我得到了如下输出:

d = inf

gcc 版本 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

在这种情况下我应该怎么做才能抛出 SIGFPE? FP 操作行为取决于哪些因素(编译器标志/CPU 类型等)?

谢谢

【问题讨论】:

标签: c++ gcc floating-point sigfpe


【解决方案1】:

只有在执行整数除以零时才会收到信号。对于浮点数,除以零是明确定义的。

这实际上在Wikipedia article 中有很好的解释。

【讨论】:

  • 我不是对你的回答吹毛求疵,只是在吹嘘 IEEE 标准中的空洞。想想这有多大意义:如果您执行 integer 除以零,则会得到 floating point exception。默认情况下,如果执行浮点除以零,则不会出现浮点异常。以数值计算为生的人往往讨厌这是默认行为。更糟糕的是,我们没有标准来获得所需的行为。除以零等,几乎总是表明事情出了差错。
  • 阅读源代码比维基百科:754r.ucbtest.org/standards/754.pdf:7.2:“如果除数为零且被除数是有限的非零数,则应发出除以零异常的信号。结果,当没有陷阱发生时,应为正确签名的 INFINITY (6.3)。”。第 8 章告诉我们,用户应该能够指定一个陷阱处理程序,当第 7 章中的任何异常发生时都会引发该处理程序。
  • 这很有趣,但目的是捕捉这种情况,因为除以零在我的上下文中是非法操作。
  • @Luther:是的,但它没有指定如何处理陷阱和异常,特别是它们不需要映射到 OS 和/或 C 风格的信号。
  • @janneb:它还说用户 应该 能够指定陷阱处理程序而不是应该。使用 should 而不是 shall 是非常有意的。捕获这些异常是一项可选功能。
【解决方案2】:

对于浮点数,您可以通过设置 FPU 控制字来更改此行为。看看here

【讨论】:

  • 我知道 FPU 控制字。在 MS 平台下可以用 _controlfp() 设置。它是否存在此函数的 POSIX 等效项?
  • @Yuri:看看你的标准包含文件&lt;fenv.h&gt;是否定义了fesettrapenable。这是非标准的,但可以广泛使用。在 linux 上,使用 feenableexcept -- 但您需要在 #include &lt;fenv.h&gt; 之前使用 #define _GNU_SOURCE
  • @Yuri S. Cherkasov 它在 fpu_control.h 中。在这里查看:christian-seiler.de/projekte/fpmath
  • @Oleg: fenv.h 通常是更好的选择。 fpu_control.h 是“在所有非 glibc 平台上缺失:MacOS X 10.5、FreeBSD 6.0、NetBSD 5.0、OpenBSD 3.8、AIX 5.1、HP-UX 11、IRIX 6.5、OSF/1 5.1、Solaris 11 2010-11、Cygwin、 mingw,Interix 3.5,BeOS"
  • 可悲的是没有标准的方法来做到这一点。更可悲的是,默认行为(至少在我使用的每台机器上)是允许除以零等。那些 Inf 和 NaN 几乎总是编程错误的结果,像兔子一样在整个数据中传播,计算缓慢数量级下降,而且很难追溯到根本原因。
【解决方案3】:

您不会收到信号,因为大多数机器上的默认行为是使用 NaN(非数字)和无穷大来污染您的数据。您必须启用浮点异常,以及如何做到这一点是特定于机器的。查看系统标题fenv.h,如果有的话。函数fesettrapenable 可以在许多机器上捕获浮点异常。

不幸的是,没有标准函数可以打开浮点异常处理。

【讨论】:

    猜你喜欢
    • 2013-07-02
    • 2010-09-29
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多