C++:使用sevcatch是安全的



我刚刚偶然发现了segvcatch库,它承诺将segfault和浮点错误打包为适当的异常。

如果我添加一个前提条件,即捕获的所有segfault都将仅为空指针访问(即,没有数组溢出或无效指针,这些指针可能在segfault之前完全破坏了内存,从而导致未定义的行为),那么使用这个库安全吗?在捕捉到一个nullptr-segfault之后,程序还会有定义的语义吗?浮点错误怎么办?他们表现得更好/不同吗?

旁注:请不要评论任何产生segfault的程序都是格式错误的,应该进行调试/修复。我知道,我同意。尽管如此,我还是对这个问题感兴趣。

不安全。

信号处理程序非常简单,它们根本就是错误的。这是SEGV处理程序:

void default_segv()
{
    throw std::runtime_error("Segmentation fault");
}

这是相当非法的,至少在POSIX上是这样。从信号处理程序中抛出异常是一个非常非常糟糕的主意。

附录
为什么这是个坏主意?

有了SIGALRM,这比一个坏主意更糟糕;这是未定义的行为,因为警报是异步的。对于SIGSEGV和SIGBUS来说,这是一个非常糟糕的主意。对于其他信号,这只是一个坏主意。有时它可能会起作用。其他时候可能不会。当魔法不起作用时,结果可能是灾难性的。

我会先看看SEGV。分段冲突和总线错误的一个常见原因是破坏堆栈。如果这是信号的原因,则没有可展开的堆栈。throw将尝试展开堆栈,这将引发另一个SEGV。现在怎么办?在我的电脑上,这是一场灾难。

不管信号是什么,在信号处理程序内部抛出相对于RAII来说都是不安全的,因为free()(因此delete)在处理程序的上下文中调用是不安全。在信号处理程序的上下文中,有一大堆函数是不安全的。处理程序中throw之后发生的一切都是在信号处理程序的上下文中完成的,因为throw不会从处理程序返回。throw绕过回路。

这些不安全的呼叫和不安全的解除意味着可以在处理旧信号的同时发出新信号。这种递归信号是非常有问题的。例如,在我的电脑上,信号变为SIGSTOP。程序不会退出,也不会丢弃核心。它只是挂在那里,永久冻结,直到我要么杀死它,要么重新启动机器。

相关内容

  • 没有找到相关文章

最新更新