Trapping floating point exceptions in Linux

Published on 2010-05-09
Tagged: linux

Working with floating point numbers in C can be a pain. If your code generates an overflow, underflow, or divide-by-zero error, the result will simply be an infinite or not-a-number value. If undefined values are used in other operations, new undefined values are generated. When your program gives inf or NaN as a result, it is difficult to tell where the error actually occurred.

Fortunately, Linux has a built-in way to catch these errors. You can enable floating point exceptions using feenableexcept. When such an exception occurs, your program will be sent the SIGFPE signal (which is always given when you have an integer divide-by-zero error). Here's some code to demonstrate:

#define _GNU_SOURCE
#include <fenv.h>

int main(void) {
    feenableexcept(FE_INVALID   | 
                   FE_DIVBYZERO | 
                   FE_OVERFLOW  | 
                   FE_UNDERFLOW);
    float a = 1., b = 0.;
    float c = a/b;
    return 0;
}

This program can be compiled by linking to the math library:

c99 fpe.c -lm -o fpe

By default, when SIGFPE is delivered the program will terminate, and a core will be dumped. This allows you to debug the program at the point where the problem first occurs. You can also install an exception handler for SIGFPE for custom error handling.

You'll need glibc 2.2 or newer in order to use feenableexcept, and you'll need to define the _GNU_SOURCE macro. C99 also defines some other handy functions for manipulating the floating point environment in a more cross-platform manner, but they don't provide a way to trap exceptions.