[英]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.