what does C/C++ handler SIGFPE?
Asked Answered
U

4

8

well, I have searched the articles about SIGFPE ,then I wrote a few tests but it's behavoir is strange. Then I have to post it here to ask for help. Is the GCC/G++ or ISO C++ clearly defined what happens if divide by zero?

1) I searched the article : Division by zero does not throw SIGFPE it sames the output is inf

2) If I rewrite it as the following:

void signal_handler (int signo) {
    if(signo == SIGFPE) {
      std::cout << "Caught FPE\n";
    }
}

int main (void) {
  signal(SIGFPE,(*signal_handler));

  int b = 1;
  int c = 0;
  int d = b/c;
  //fprintf(stderr,"d number is %d\n,d);
  return 0;
}

then signal_handler will not happens. but if I uncomment the line

//fprintf(stderr,"d number is %d\n,d);

then signal_handler keeps calling.

can someone explains it ?

Uxmal answered 16/2, 2013 at 1:25 Comment(3)
Integer division by zero still raises SIGFPE (floating point error), but floating point division by zero yields infinity as the answer.Champollion
int c = 0; int d = b/c; ? which means b/0 ?Tenno
I don't reproduce you exacly: I get the signal only once and then the program exits, with or without the printf. If I add signal(SIGFPE,(*signal_handler)); inside the signal handler, then I reproduce you. Linux 3.10, gcc 4.7.3.Brian
D
5

This is interesting: With the fprintf commented out, the compiler has determined that the calculated result: d = b/c is an unused local expression and can be optimized away.

Clearly though, it is not side-effect free in its execution, but the compiler can't determine anything about the runtime environment at this stage. I'm surprised that static analysis doesn't pick this up as a warning (at least) in a modern compiler.

@vonbrand is right. You got lucky with what you're doing in the (asynchronous) signal handler.


Edit: when you say "signal_handler keeps calling", do you mean it's repeating indefinitely? If so, there could be issues with underlying system calls restarting. Try: siginterrupt(SIGFPE, 1); (assuming it's available).

Dogged answered 16/2, 2013 at 1:38 Comment(0)
G
3

There are only a few operations allowed in signal handlers, and using any buffered I/O (std::cout et al, but also fprintf(3), which BTW I don't know if it mixes well with the previous one) is out of the question. See signal(7) for the restrictions.

Gillman answered 16/2, 2013 at 1:35 Comment(0)
T
3

Why signal_handler will not happens: compiler optimization killed division for unused result.

Why signal_handler keeps calling: After return from signal handler, FPE re-execute same instruction. You can avoid it by using longjmp.

Here is my well-working code for the purpose (at least on Mac OS X) https://github.com/nishio/learn_language/blob/master/zero_division/zero_division.cpp

Trella answered 19/5, 2014 at 2:41 Comment(1)
Seems to work on g++ and clang++ on ubuntu tooBipetalous
F
1

Is the GCC/G++ or ISO C++ clearly defined what happens if divide by zero?

As far as the standard goes, division by zero is Undefined Behaviour, anything could happen.

In practice, even though the standard says it is UB, it is actually implementation-defined at the OS (not language/compiler) level. On POSIX this will indeed generate a SIGFPE, on Windows it will throw an exception (Windows' SEH exception, not a C++ exception even though some compilers additionally map SEH to C++ exceptions), etc.

if I uncomment the line //fprintf(stderr,"d number is %d\n,d); then signal_handler keeps calling. can someone explains it ?

As others have said, this is because the compiler detects that d is never used and optimizes away the calculation (as well as the b and c definitions in all probability). This happens because the language can't foresee what will happen (remember, it's UB) so it might as well assume nothing happens.

Froebel answered 16/2, 2013 at 3:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.