Trapping floating point exceptions in 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.