如何将 SIGFPE 转换为C++例外
How to convert SIGFPE into a C++-exception
在Win32下,很容易将SEH异常转换为_set_se_translator C++异常。在 Linux 上是否有类似的方法将某些信号转换为C++异常?我需要将 SIGFPE 映射到C++异常。
使用 g++,您可以使用-fnon-call-exceptions
选项,只需从 FPE 信号处理程序中抛出异常。请注意,并非每个信号都可以这样映射,只有捕获指令产生的信号才能映射。幸运的是,SIGFPE就是这样一个信号。
在 Linux 等 POSIX 系统上,您无法可靠地做到这一点。有关更多详细信息,另请参阅此处。请注意,在你的情况下不能使用 signalfd(2)。我假设您正在x86-64或其他一些常用的体系结构上使用Linux。
仔细阅读 signal(7)(特别是关于信号处理程序中的异步信号安全函数的说法,它们是处理像 SIGFLE
这样的信号的唯一方法)。另请阅读 C++11 标准或 C99 标准对signal
的看法。大多数C++实现有时可能会生成一些对运行时支持函数的隐式调用,这些函数不是异步信号安全的(特别是那些用于引发异常的函数)。因此,您无法可靠地从信号处理程序引发异常)。
实际上,以下内容将是错误的信号处理程序:
/// 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++运行时),如 __cxa_allocate_exception
、__cxa_throw
、_Unwind_Resume
信号(7) 禁止的函数。
不abort
或_exit
的信号处理程序,唯一安全的做法是设置一些volatile sigatomic_t
标志,或使用一些异步信号安全函数,例如在管道(7)上写入(2)某些内容。此外,从信号处理程序引发异常并不比从中调用printf
更糟糕(很多人都错误地这样做);这是被禁止的,但它通常可以工作。我仍然不建议这样做,特别是在长时间运行的程序中,或者崩溃 - 即使不经常 - 也是不可接受的。
的信息,特别是Lattner的博客,关于每个C程序员都应该知道的关于未定义行为的知识。
在实践中,处理信号的唯一可靠和可移植的方法是拥有一个信号处理程序,它只是设置一些volatile sigatomic_t
标志。但是,如果您这样做SIGFPE
您的实现很可能会在相同的状态下重新启动相同的计算,从而无限期地循环SIGFPE
处理。另请参阅有关-fnon-call-exceptions
的这个(所以我相信n.m.的答案可能并不总是正确和可靠的;事实上,它是未定义的行为,通常看起来有效)。
实际上,我强烈怀疑Windows进行转换的方式不符合C++11或C++14标准(或C99或C11标准),您可以在Windows上有一个符合C++(或C99或C11)的标准实现,这不允许做你的建议;可能Clang或GCC就是这样的实现。
- 将 ctypes 与 tesserac-ocr 一起使用的例外 TessPageIteratorBoundingBox.
- 为什么程序员同时使用 std::bad_alloc 和 std::exception.是否 std::例外 仅是不够的
- 继承 C++11 中的例外?
- C++ - 为什么这有很强的例外保证?
- 与 boost::locale 关于"ß"大写的例外行为混淆
- Chrome GN 例外已禁用
- 如何在 x64 上"stack oveflow"例外
- 使用 stod() 转换小数点后字母的字符串时没有例外
- 该标准是否说明了例外和不同调用约定的共存
- 例外:'Access violation reading location'
- 为什么复制省略是"好像"规则的一个例外
- 为什么我在此删除中有例外?
- 常量字符*是否有任何例外?
- Windows 并发运行时任务计划,但有例外
- 为什么 string::replace 在 C++11 中没有指定分配器的例外?
- 有什么东西阻止std::optional::value_or()有条件地不例外吗?
- MATLAB API用于使用MatgetDir的C例外:Matrix :: Serialize ::在内存位置内置
- 通过C函数调用扔C 例外
- Xcode会产生分割故障,而不是例外
- 安全地向DTOR抛出例外