Search code examples
c++clinuxfloating-point-exceptions

How to disable floating point exceptions in C/C++ code?


In my C or C++ code I want division by 0 to result in a float value +Infinity or -Infinity, calling sqrt(-1) or log(0) to produce a float value of NaN, etc. per the IEE754 spec. The current behavior I see when any of these things happen is a floating point exception. It is out of the scope of my program to catch exceptions, as it is performing a large number of operations and then performing an aggregate function, so if even a single NaN or infinity it must "poison" the results and make it an infinity or not-a-number.

I mention C and C++ because there is some interoperability, e.g. a C function compiled to a shared object library that may perform the floating point operation but get called from C++.

I originally was able to write some C code and it seemed the default was to NOT throw an exception. However, this was throwaway code to test what the behavior was and unfortunately I did not save it. Now when I try it I am not able to get back to the point where I can get a NaN into a float and then print it, instead I get an exception.

In C++ I am using:

#include <cfenv>

then in my code before I call the function that may generate an infinity or NaN I do this:

std::fenv_t envp;
// Clear all floating-point exceptions (not strictly necessary?)
std::feclearexcept(FE_ALL_EXCEPT);
// save floating point environment and then don't generate exceptions
std::feholdexcept(&envp);

// Disable all floating-point exceptions (just for good measure)
fedisableexcept(FE_ALL_EXCEPT);

I am compiling this using g++ with these flags:

-fno-trapping-math -fno-signaling-nans

In C I am using a similar approach:

#include <fenv.h>
#pragma STDC FENV_ACCESS ON

int main() {
    fenv_t envp;
    printf("debug0:%d\n",feholdexcept(&envp));
    printf("debug1:%f\n",1/0);
}

note: I tried the pragma in my C++ code but g++ did not recognize the pragma.

gcc -fno-trapping-math -fno-signaling-nans -o test test.c -lm

gcc version is 6.3, g++ version is 6.5 (I don't have the option for a newer version at the moment as these are running on production systems.)


Solution

  • The expression 1/0 is triggering an exception because you're doing division by zero with integers. There's no floating point type involved here.

    Where the division by zero is happening in your actual code must be done with floating point types in order for the result generate an INF value.