2012-09-13 45 views
4

我只是偶然发现了segvcatch库,它承诺将段错误和浮点错误包装为适当的异常。C++:是否使用segvcatch安全?

如果我添加了前提条件,即捕获的所有段错误只会是空指针访问(即没有数组溢出或无效指针可能在段错误之前完全搞乱了内存,导致未定义的行为) )?在捕获nullptr段错误之后,程序是否仍然定义了语义?什么是浮点错误?他们的表现更好/不同?

旁注:请不要评论任何产生段错误的程序无论如何都是不合格的,应该调试/修复。我知道这一点,我同意。不过,我对这个问题感兴趣。

+0

这个segvcatch是一个奇怪的事情。它工作吗?它会花费什么(性能明智)? – Walter

+0

@Walter:那么,至少测试用例似乎在Linux下工作。 – gexicide

回答

4

不安全。

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

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

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

增编
那么为什么这是一个坏主意?

使用SIGALRM,这比糟糕的想法更糟;它是未定义的行为,因为警报是异步的。使用SIGSEGV和SIGBUS这是一个非常糟糕的主意。有了其他信号,这只是一个坏主意。它有时可能有效。其他时候,它可能不会。当魔法无效时,结果可能会非常糟糕。

我会先看看SEGV。分段违规和总线错误的一个常见原因是粉碎堆栈。如果这是信号的原因,没有堆栈可以放松。 throw将尝试展开堆叠,这将引发另一个SEGV。怎么办?在我的电脑上,这是一场灾难。

不管信号如何,抛入信号处理程序对于RAII来说都不安全,因为free()(因此delete)在处理程序的上下文中不安全。从信号处理器的上下文中调用一些函数是不安全的。处理器中的throw之后发生的所有事情都是从信号处理程序的上下文中完成的,因为throw不会从处理程序返回。 throw绕过回报。

那些不安全的调用和不安全的解除意味着在处理旧信号的同时可以产生新的信号。这个递归信号是非常有问题的。例如,在我的电脑上,信号变成了SIGSTOP。该程序不退出,它不会退出核心。它只是挂在那里,永久冻结,直到我杀死它或重新启动机器。

+0

好的,但它在gcc中有效,特别是-fnon-call-exceptions。虽然有点不同:http://stackoverflow.com/questions/5860999/why-doesnt-my-signal-handler-which-throws-an-exception-trigger-more-than-once – queen3

+0

大卫,**为什么**这是一个非常非常糟糕的主意吗?为什么在C++ 11中是非法的? @ queen3使用'-fnon-call-exceptions'时有什么意义? – Walter

+0

谢谢沃尔特,好评!另外,图书馆似乎会在segfault方面做一些魔术,比如调整个人电脑和东西。所以你发布的处理程序不是库的唯一贡献(一行信号处理程序不需要自己的库...) – gexicide