17

I have a small program performing floating-point division by zero, so I expect 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;
}

Actually, I got the following output:

d = inf

gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

What should I do to throw SIGFPE in this case? Which factors FP operation behaviour depend on (compiler flags/CPU type and so on)?

Thanks

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 2
    This should be pretty standarrd if you have IEEE floats. – Ingo Sep 01 '11 at 08:40
  • Similar question: [Can I make gcc tell me when a calculation results in NaN or inf at runtime?](http://stackoverflow.com/questions/2941611/can-i-make-gcc-tell-me-when-a-calculation-results-in-nan-or-inf-at-runtime) – sleske Jul 03 '13 at 08:10

3 Answers3

12

You only get a signal if you perform an integer division by zero. For floating point numbers, division by zero is well defined.

This is actually explained rather well in the Wikipedia article.

Motti
  • 110,860
  • 49
  • 189
  • 262
  • 3
    I'm not carping at your answer, just carping at that inanity in the IEEE standard. Think how much sense this makes: You get a *floating point exception* if you perform an *integer* division by zero. By default, you don't get a floating point exception if you perform a floating point divide by zero. People who do numerical computing for a living tend to hate that this is the default behavior. Worse, there is no standard we to get the desired behavior. Division by zero, etc., are almost always a sign something has gone awry. – David Hammen Sep 01 '11 at 09:25
  • 5
    Reading the source beats wikipedia: http://754r.ucbtest.org/standards/754.pdf : 7.2: "If the divisor is zero and the dividend is a finite nonzero number, then the division by zero exception shall be signaled. The result, when no trap occurs, shall be a correctly signed INFINITY (6.3).". And chapter 8 tells us that the user should be able to specify a trap handler, which is raised when any of the exceptions in ch.7 occur. – Nordic Mainframe Sep 01 '11 at 09:36
  • That's interesting, but the purpose is to catch such situations, because division by zero is illegal operation in my context. –  Sep 01 '11 at 10:26
  • 1
    @Luther: Well yes, but it doesn't specify how traps and exceptions are handled, and in particular they don't need to map to OS and/or C style signals. – janneb Sep 01 '11 at 13:11
  • 1
    @janneb: It also says *the user* **should** *be able to specify a trap handler* rather than *shall*. The use of should rather than shall is quite intentional. Trapping those exceptions is an optional feature. – David Hammen Sep 01 '11 at 13:28
7

For floating point numbers you can change this behavior by setting up FPU control word. Take a look here

Oleg
  • 798
  • 3
  • 7
  • I know about FPU control word. It might be set with _controlfp() under MS platform. Does it exist the POSIX equivalent for this function? –  Sep 01 '11 at 10:18
  • 3
    @Yuri: See if your standard include file `` defines `fesettrapenable`. This is non-standard but is widely available. On linux, use `feenableexcept` -- but you need to `#define _GNU_SOURCE` before you `#include `. – David Hammen Sep 01 '11 at 11:09
  • 1
    @Yuri S. Cherkasov It's in fpu_control.h. Check here: http://www.christian-seiler.de/projekte/fpmath/ – Oleg Sep 01 '11 at 12:18
  • 1
    @Oleg: `fenv.h` is usually a better bet. `fpu_control.h` is "missing on all non-glibc platforms: 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" – David Hammen Sep 01 '11 at 13:34
  • @David Hammen, Agree. But topic starter is using Ubuntu, so it should be ok for him. (again - agree about cross-platform, etc.) – Oleg Sep 02 '11 at 07:06
  • 1
    The sad thing is that there is no standard way to do this. Even sadder is that the default behavior (at least on every machine I have used) is to allow division by zero, etc. Those Infs and NaNs are almost always a result of a programming error, propagate like bunny rabbits throughout the data, slow calculations down by orders of magnitude, and can be very hard to trace back to the root cause. – David Hammen Sep 02 '11 at 12:12
6

You don't get a signal because the default behavior on most machines is to pollute your data with NaNs (not-a-number) and infinities. You have to enable floating point exceptions, and how you do that is machine specific. Look at the system header fenv.h, if you have one. The function fesettrapenable enables catching floating point exceptions on many machines.

Unfortunately, there is no standard function to turn floating point exceptions handling on.

David Hammen
  • 32,454
  • 9
  • 60
  • 108