结构化异常处理程序(SEH)无法捕获堆栈破坏问题。

4
我正在编写一个小工具(VC 2010,无clr),使用第三方库执行一项简单任务(光栅化)。稍后这个工具将被更大的应用程序使用。有时,由于第三方库中的某些堆破坏,该工具会崩溃。虽然如此,但Windows(Vista/2008)会显示一个众所周知的对话框“程序已停止工作...关闭/调试程序。”这在我的情况下(服务器端)并不合适。该工具应该在没有任何可见影响的情况下默默地崩溃/终止。
为此,我安装了SEH以处理未处理的异常(SetUnhandledExceptionFilter)。对于诸如AV(*(PDWORD)0 = 0)之类的异常,处理程序完美地被调用,但由于某种原因,在堆破坏的情况下,处理程序没有被调用。破坏发生在其中一个第三方库dll的dllmain中,当它被卸载时。
几个问题。有人能解释为什么处理程序没有被调用吗?还有其他方法可以防止该对话框吗?

1
DllMain()是特殊的。Windows不能允许失败,否则会严重破坏进程。它在运行时捕获SEH异常,因此您的过滤器无法起作用。你能做的不多,只能修复错误。在服务器上禁用WER,在serverfault.com上提问相关问题。 - Hans Passant
1
谢谢,汉斯。这很有道理。我会尝试用另一种方式解决我的初始问题。 - AC.
2
此外,在某些情况下,这可能是问题所在: https://dev59.com/aWIk5IYBdhLWcg3wBqGW - Maxim Kogan
2个回答

4
显然,故意发生的堆栈损坏无法被用户定义的异常处理程序捕获,尽管它们是带有自己异常代码(0xC0000374“STATUS_HEAP_CORRUPTION”)的异常。这是一个Visual C++错误报告,基本上被关闭为“不予修复”:https://connect.microsoft.com/VisualStudio/feedback/details/664497/cant-catch-0xc0000374-exception-status-heap-corruption

如你所发现的,这不是编译器或操作系统中的错误。您的函数引起的堆损坏被视为严重错误的一部分,并在处理该错误时,操作系统终止进程。这就是导致您的异常处理程序未被调用的原因。

我猜Windows错误报告或其他创建崩溃转储的方法仍然可以捕获它。
至于防止对话框,在注册表中可以完全禁用WER或仅禁用对话框,以便进程不会阻塞:https://msdn.microsoft.com/de-de/library/windows/desktop/aa366711(v=vs.85).aspx(参见“DontShowUI”)。

1
但由于某种原因,在堆损坏的情况下不会调用它。在卸载其中一个第三方库dll时,dllmain中发生了损坏。
堆损坏是未定义的行为。它可能会抛出异常,也可能会做其他事情。如果有错误的第三方库搞乱了你的堆栈,那么问题就是“为什么你要让他们首先搞乱你的堆栈呢?”
“程序已停止工作”对话框会在进程异常终止时显示。并非所有异常进程终止都会导致异常。许多错误(例如堆栈溢出、堆栈错位等)会导致进程立即终止,这可能会显示该消息,但不会给您处理错误的机会。
(另请参见上面Hans的精彩评论)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接