简体   繁体   English

C / C ++处理程序SIGFPE是什么?

[英]what does C/C++ handler SIGFPE?

well, I have searched the articles about SIGFPE ,then I wrote a few tests but it's behavoir is strange. 好吧,我搜索了有关SIGFPE的文章,然后我写了一些测试,但它的行为很奇怪。 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? GCC / G ++或ISO C ++是否明确定义了如果除以零会发生什么?

1) I searched the article : Division by zero does not throw SIGFPE it sames the output is inf 1)我搜索了这篇文章: 除零之后不会抛出SIGFPE同样输出是inf

2) If I rewrite it as the following: 2)如果我重写如下:

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. 然后signal_handler将不会发生。 but if I uncomment the line 但如果我取消注释该行

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

then signal_handler keeps calling. 然后signal_handler继续打电话。

can someone explains it ? 有人可以解释一下吗?

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. 这很有趣:在fprintf注释掉后,编译器确定计算结果: d = b/c是一个未使用的本地表达式,可以进行优化。

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. @vonbrand是对的。 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? 编辑:当你说“signal_handler一直在呼唤”时,你的意思是它无限期地重复吗? If so, there could be issues with underlying system calls restarting. 如果是这样,可能会出现重启基础系统调用的问题。 Try: siginterrupt(SIGFPE, 1); 尝试: siginterrupt(SIGFPE, 1); (assuming it's available). (假设它可用)。

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. 在信号处理程序中只允许一些操作,并且使用任何缓冲的I / O( std::cout等人,还有fprintf(3) ,BTW我不知道它是否与之前的混合很好)不可能的。 See signal(7) for the restrictions. 有关限制,请参阅signal(7)

Why signal_handler will not happens: compiler optimization killed division for unused result. 为什么signal_handler不会发生:编译器优化会因未使用的结果而导致分裂。

Why signal_handler keeps calling: After return from signal handler, FPE re-execute same instruction. 为什么signal_handler一直在调用:从信号处理程序返回后,FPE重新执行相同的指令。 You can avoid it by using longjmp. 您可以使用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 这是我用于此目的的良好代码(至少在Mac OS X上) https://github.com/nishio/learn_language/blob/master/zero_division/zero_division.cpp

Is the GCC/G++ or ISO C++ clearly defined what happens if divide by zero? GCC / G ++或ISO C ++是否明确定义了如果除以零会发生什么?

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. 实际上,即使标准说它是UB,它实际上是在OS(而不是语言/编译器)级别实现定义的。 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. 在POSIX上,这确实会生成一个SIGFPE,在Windows上会抛出异常(Windows的SEH异常,而不是C ++异常,即使某些编译器还将SEH映射到C ++异常)等。

if I uncomment the line //fprintf(stderr,"d number is %d\\n,d); then signal_handler keeps calling. can someone explains it ? 如果我取消注释//fprintf(stderr,"d number is %d\\n,d);然后signal_handler继续调用。有人可以解释吗?

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). 正如其他人所说的那样,这是因为编译器检测到d从未使用过并且优化了计算(以及所有概率中的bc定义)。 This happens because the language can't foresee what will happen (remember, it's UB) so it might as well assume nothing happens. 发生这种情况是因为语言无法预见会发生什么(记住,它是UB)所以它也可能假设没有任何反应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM