在Win32下,使用_set_se_translator很容易将SEH异常转换为C ++异常。是否有类似的方法将某些信号转换为C ++ - Linux上的例外?我需要将SIGFPE映射到C ++ - 异常。
答案 0 :(得分:2)
使用g ++,您可以使用-fnon-call-exceptions
选项,只是从FPE信号处理程序中抛出异常。请注意,并非每个信号都可以像这样映射,只有信号来自陷阱指令。幸运的是,SIGFPE就是这样一个信号。
答案 1 :(得分:1)
您无法在Linux等POSIX系统上可靠。有关详细信息,另请参阅this。请注意,在您的情况下,您无法使用signalfd(2)。我假设您在x86-64或其他常用架构上使用Linux。
仔细阅读signal(7)(特别是关于信号处理程序中 async-signal-safe 函数的说法,它们是处理SIGFLE
等信号的唯一方法)。另请阅读C ++ 11标准或C99标准关于signal
的内容。大多数C ++实现有时可能会为运行时支持函数生成一些隐式调用,这些函数不是 async-signal-safe (特别是那些抛出异常的函数。所以你不能可靠地抛出来自信号处理程序的异常。)
在实践中,以下将是错误的信号处理程序:
/// 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");
}
您可以通过编译g++ -Wall -O -fverbose-asm -S
(然后查看发出的.s
汇编程序文件)进行检查,它正在调用一些非异步信号安全函数(来自C ++运行时),如{ {1}},__cxa_allocate_exception
,__cxa_throw
禁止 signal(7) ....
实际上,从_Unwind_Resume
或abort
的信号处理程序中唯一安全的做法是设置一些_exit
标志,或使用少数 async-signal-safe 功能,例如write(2)上的pipe(7)内容。另外,从信号处理程序中抛出异常并不比从它调用volatile sigatomic_t
更糟糕(许多人错误地这样做);它是被禁止的,但它经常可以工作。我仍然不建议这样做,特别是在长时间运行的程序中,或者不经常发生崩溃的情况下。
详细了解undefined behavior,特别是Lattner关于What every C programmer should know about undefined behavior的博客。
实际上,处理信号的唯一可靠且可移植的方法是使用信号处理程序,只设置一些printf
标志。但是如果你为volatile sigatomic_t
执行此操作,则您的实现很可能会在相同的状态下重新启动相同的计算,因此在SIGFPE
处理时无限循环。另请参阅this关于-fnon-call-exceptions
(因此我认为n.m.'s answer可能并不总是正确且可靠;事实上它似乎是未定义的行为,通常似乎有用。)
PS。实际上,我强烈怀疑Windows进行转换的方式不符合C ++ 11或C ++ 14标准(或C99或C11标准),并且您可以使用C ++(或C99或C11)的标准符合实现Windows不允许做你的建议;可能Clang或GCC就是这样的实现。