为什么Windows在WM_CLOSE期间吞下异常

Bra*_*son 17 winapi exception-handling

在试图找出我正在处理的应用程序无法关闭的原因时,我意识到它在WM_CLOSE处理程序中抛出异常.但是,不是应用程序崩溃(应该如此),而是以静默方式忽略异常.

为了确保没有其他东西在进行,我在Visual Studio中创建了一个新的C++ Win32应用程序并添加了以下内容:

case WM_CLOSE:
    (*(int*)NULL) = 0;
    break;
Run Code Online (Sandbox Code Playgroud)

同样的事情:没有崩溃,只是调试日志中的第一次机会异常.如果我将相同的代码添加到WM_COMMAND处理程序,它会按预期崩溃.

所以我很好奇:有什么特别之处WM_CLOSE在于Windows认为应该吞下它抛出的异常?

(顺便说一句:这是在Windows 7 x64上,运行x86程序)

Mar*_* Ba 2

Win 64 上的异常被吞掉WindowProc是预期的行为。(参见文档。)

\n\n

另请参阅Paul Betts博客上的更好解释,尤其是他的注释

\n\n
\n

为什么这种情况不总是\xe2\x80\x99 发生?

\n\n

这里\xe2\x80\x99解释为什么这种情况似乎只发生在某些窗口消息上\xe2\x80\x93\n记住窗口消息可以来自不同的源,\n任何人(*)都可以将消息排队到窗口。然而,某些窗口消息是通过 win32k.sys 直接发送的(最值得注意的是 WM_CREATE),作为用户模式调用的直接同步结果。

\n
\n\n

似乎对这个问题有所启发。

\n\n

随机 ASCII对于所有这些内核模式前吞噬行为也有一些很好的解释:

\n\n
\n

完全无法停下来

\n\n

几年前,64 位 Windows 引入了一个同样令人不安的问题,它导致一些崩溃被默默地忽略。

\n\n

结构化异常...依赖于能够展开堆栈(无论是否调用析构函数),以便将执行从发生异常的位置转移到 catch/__ except 块。

\n\n

64 位 Windows 的引入使这一情况变得更加复杂。在 64 位 Windows 上, 不可能跨内核边界展开堆栈。也就是说,如果...在应该在内核边界的另一侧处理的回调中抛出异常,则 Windows 无法处理此问题。

\n\n

这可能看起来有点深奥,不太可能 \xe2\x80\x93 编写内核回调\n 似乎是一个罕见的活动 \xe2\x80\x93 但它 \xe2\x80\x99 实际上很常见。特别是,WindowProc是一个回调,它通常由内核调用,...

\n
\n\n

作为奖励:请参阅此处,了解原因

\n