Trapping floating-point overflow in C

2020-04-06 06:06发布

问题:

I am trying to trap floating-point overflow in C. Here is what I have tried

#define _GNU_SOURCE

#include <fenv.h>
#include <signal.h>
#include <stdio.h>

void catch_overflow (int sig) {   
  printf ("caught division by zero\n");   
  signal (sig, catch_overflow); 
}


int main(void) {   
  feenableexcept(FE_DIVBYZERO);   
  signal (FE_DIVBYZERO, catch_overflow);


  float a = 1., b = 0.;   float c = a/b;   return 0; }

I expected to see "caught division by zero" message, but I only get a core dump message, "Floating point exception (core dumped)". How could I modify the program to get the "caught division by zero" message?

Thanks.

回答1:

A floating point exception is translated in machine- and OS-dependent way to some signaling approach. But no such way allows mixing of different constant spaces, as FE_xxx and SIGxxx. Using FE_DIVBYZERO for signal(), you really caught SIGILL which is not generated for floating-point errors (because you did not specify OS, I was free to choose any - Linux in my case).

For your program, I have made this exception catching working under Linux with two changes:

  1. Setting signal number to handle to SIGFPE.

  2. Declaring a, b, c as volatile (prevents compiler from calculating c as INF at compile time).

After this, the program fell into eternal cycle printing "caught division by zero" because signal handler for such error restores execution to the same command. You shall carefully consider how to fix such errors without making an erroneous instruction eternal. For example, you can use longjmp to go out of signal handler to an installed exception handler.

And, you still should consult your target OS manuals for how to catch FP errors.

(This has been already described in comments in main parts - but I considered to form an explicit answer.)