简体   繁体   English

如何将SIGFPE转换为C ++异常

[英]How to convert SIGFPE into a C++-exception

Under Win32 it's easy to convert a SEH-exception into a C++-exception with _set_se_translator. 在Win32下,使用_set_se_translator将SEH异常转换为C ++异常很容易。 Is there a similar way to convert certain signals into C++-exceptions on Linux? 在Linux上是否有类似的方法将某些信号转换为C ++异常? I need a mapping of SIGFPE to a C++-exception. 我需要将SIGFPE映射到C ++异常。

With g++, you can use -fnon-call-exceptions option and just throw an exception from the FPE signal handler. 使用g ++,您可以使用-fnon-call-exceptions选项,并且仅从FPE信号处理程序中引发异常。 Note not every signal can be mapped like that, only signals that arise from trapping instructions. 请注意,并非每个信号都可以那样映射,只有捕获指令产生的信号才能映射。 Fortunately SIGFPE is such a signal. 幸运的是,SIGFPE就是这样的信号。

You cannot do reliably that on POSIX systems such as Linux. 您不能在Linux等POSIX系统上可靠地做到这一点。 See also this for more details. 另请参阅以获取更多详细信息。 Notice that you can't use signalfd(2) in your case. 请注意,您不能在这种情况下使用signalfd(2) I assume you are using Linux on x86-64 or some other commonly available architecture. 我假设您正在x86-64或其他一些常用架构上使用Linux。

Read very carefully signal(7) (in particular what is said about async-signal-safe functions in signal handlers, and they are the only way to handle signals like SIGFLE ). 仔细阅读signal(7) (特别是关于信号处理程序中的异步信号安全函数的说法,它们是处理SIGFLE信号的唯一方法)。 Read also what the C++11 standard or the C99 standard say about signal . 另请阅读C ++ 11标准或C99标准关于signal Most C++ implementations might sometimes generate some implicit call to runtime support functions which are not async-signal-safe (in particular, those for throwing an exception. So you cannot reliably throw an exception from a signal handler). 大多数C ++实现有时可能会生成对运行时支持函数的隐式调用 ,这些调用不是异步信号安全的 (特别是那些引发异常的函数。因此,您不能可靠地从信号处理程序中引发异常)。

In practice, the following would be a wrong signal handler : 实际上,以下是错误的信号处理程序

/// WRONG CODE, against signal(7) since calling 
/// non-async-signal-safe functions from the C++ runtime
void badSIGFPEhandler(int sig) {
  if (sig == SIGFPE)
    throw std::runtime_error("got SIGFPE");
}    

You can check by compiling it with g++ -Wall -O -fverbose-asm -S (then looking into the emitted .s assembler file) that it is calling some non-async-signal-safe functions (from the C++ runtime) like __cxa_allocate_exception , __cxa_throw , _Unwind_Resume which is forbidden by signal(7) .... 您可以通过使用g++ -Wall -O -fverbose-asm -S进行编译(然后查看发出的.s汇编文件)来检查它是否正在调用某些非异步信号安全函数(来自C ++运行时),例如__cxa_allocate_exception__cxa_throw_Unwind_Resume ,这是signal(7) 禁止的

In practice, the only safe thing to do from a signal handler which does not abort or _exit is to set some volatile sigatomic_t flag, or use the few async-signal-safe functions, eg write(2) something on a pipe(7) . 实际上,从不会abort_exit的信号处理程序中唯一安全的事情是设置一些volatile sigatomic_t标志,或使用一些异步信号安全功能,例如write(2)pipe(7)上执行操作 Also, throwing an exception from a signal handler is not worse than calling printf from it (lots of people are wrongly doing it); 另外,从信号处理程序中引发异常并不比从信号处理程序中调用printf差(很多人错误地执行了此操作)。 it is forbidden, but it could often work. 禁止使用它,但是它通常可以正常工作。 I still don't recommend doing that, in particular in programs which are running for a long time, or for which crashing -even infrequently- is not acceptable. 我仍然不建议这样做,尤其是在运行时间较长的程序中,或者对于崩溃(即使很少发生)也不可接受的程序。

Read more about undefined behavior , notably Lattner's blog about What every C programmer should know about undefined behavior . 阅读有关未定义行为的更多信息,尤其是Lattner的博客,其中介绍了每个C程序员应了解的未定义行为

In practice, the only reliable and portable way to handle signals is to have a signal handler which just sets some volatile sigatomic_t flag. 实际上,处理信号的唯一可靠且可移植的方法是拥有一个仅设置一些volatile sigatomic_t标志的信号处理程序。 But if you do that for SIGFPE your implementation is very likely to restart the same computation in the same state, hence looping indefinitely on SIGFPE handling. 但是,如果对SIGFPE执行此操作,则您的实现很有可能在相同状态下重新启动相同的计算,从而无限期地循环处理SIGFPE See also this regarding -fnon-call-exceptions (so I believe that nm's answer might not always be right and reliable; it is in fact undefined behavior which would often seem to work). 另请参见关于-fnon-call-exceptions (所以我相信纳米的回答可能并不总是对的,可靠的,它实际上是不确定的行为,往往会似乎工作)。

PS. PS。 Actually, I strongly suspect that Windows way of doing that conversion is not C++11 or C++14 standard (or C99 or C11 standard) conforming, and you could have a standard conforming implementation of C++ (or C99 or C11) on Windows which disallows doing what you suggest; 实际上,我强烈怀疑Windows进行该转换的方式不符合C ++ 11或C ++ 14标准(或C99或C11标准),并且您可能在Windows上具有符合标准的C ++(或C99或C11)实现。 Windows无法执行您的建议; and probably Clang or GCC are such implementations. 可能是Clang或GCC就是这样的实现。

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

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