Division by zero does not throw SIGFPE
Asked Answered
E

3

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

Elastomer answered 1/9, 2011 at 8:33 Comment(2)
This should be pretty standarrd if you have IEEE floats.Aulos
Similar question: Can I make gcc tell me when a calculation results in NaN or inf at runtime?Doorjamb
G
7

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

Getaway answered 1/9, 2011 at 8:58 Comment(6)
I know about FPU control word. It might be set with _controlfp() under MS platform. Does it exist the POSIX equivalent for this function?Elastomer
@Yuri: See if your standard include file <fenv.h> defines fesettrapenable. This is non-standard but is widely available. On linux, use feenableexcept -- but you need to #define _GNU_SOURCE before you #include <fenv.h>.Graduated
@Yuri S. Cherkasov It's in fpu_control.h. Check here: christian-seiler.de/projekte/fpmathGetaway
@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"Graduated
@David Hammen, Agree. But topic starter is using Ubuntu, so it should be ok for him. (again - agree about cross-platform, etc.)Getaway
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.Graduated
W
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.

Whitman answered 1/9, 2011 at 8:49 Comment(5)
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.Graduated
Reading the source beats wikipedia: 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.Shrewish
That's interesting, but the purpose is to catch such situations, because division by zero is illegal operation in my context.Elastomer
@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.Sotos
@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.Graduated
G
7

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

Getaway answered 1/9, 2011 at 8:58 Comment(6)
I know about FPU control word. It might be set with _controlfp() under MS platform. Does it exist the POSIX equivalent for this function?Elastomer
@Yuri: See if your standard include file <fenv.h> defines fesettrapenable. This is non-standard but is widely available. On linux, use feenableexcept -- but you need to #define _GNU_SOURCE before you #include <fenv.h>.Graduated
@Yuri S. Cherkasov It's in fpu_control.h. Check here: christian-seiler.de/projekte/fpmathGetaway
@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"Graduated
@David Hammen, Agree. But topic starter is using Ubuntu, so it should be ok for him. (again - agree about cross-platform, etc.)Getaway
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.Graduated
G
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.

Graduated answered 1/9, 2011 at 9:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.