gex*_*ide 5 c++ signals exception-handling segmentation-fault
我偶然发现了segvcatch库,它承诺将segfaults和浮点错误包装到适当的异常中.
使用这个库是安全的,如果我添加了捕获的所有段错误只会是空指针访问的前提条件(即,没有数组溢出或无效指针可能在segfaulting之前完全搞砸了内存,导致未定义的行为无论如何)?在捕获nullptr段错误后,程序是否仍然定义了语义?浮点错误呢?他们表现得更好/不同吗?
旁注:请不要评论说任何产生段错误的程序都是格式错误的,应该进行调试/修复.我知道,我同意.不过,我对这个问题很感兴趣.
不安全.
信号处理程序非常简单,它们完全错了.这是SEGV处理程序:
void default_segv()
{
throw std::runtime_error("Segmentation fault");
}
Run Code Online (Sandbox Code Playgroud)
这是非常非法的,至少在POSIX上.从信号处理程序中抛出异常是一个非常非常糟糕的主意.
附录
那么为什么这是一个坏主意呢?
使用SIGALRM,它比一个坏主意更糟糕; 它是未定义的行为,因为警报是异步的.使用SIGSEGV和SIGBUS,这是一个非常糟糕的主意.有了其他信号,这只是一个坏主意.它有时会起作用.其他时候,它可能不会.当魔法不起作用时,结果可能是灾难性的.
我先看看SEGV.分段违规和总线错误的一个常见原因是粉碎堆栈.如果这是信号的原因,则没有堆叠可以展开.该throw会尝试展开栈,这将提高其他SEGV.怎么办?在我的电脑上,这是一场灾难.
无论信号如何,抛出信号处理程序对RAII来说都是不安全的,因为free()(并因此delete)在处理程序的上下文中调用是不安全的.在信号处理程序的上下文中,有一大堆函数不安全.throw在处理程序之后发生的所有事情都是在信号处理程序的上下文中完成的,因为throw它不会从处理程序返回.在throw绕过回报.
那些不安全的呼叫和不安全的退绕意味着可以在处理旧信号时发出新信号.这种递归信号很成问题.例如,在我的计算机上,信号变为SIGSTOP.该程序不会退出,它不会丢弃核心.它只是挂在那里,永久冻结,直到我杀死-9或重启机器.