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

时间:2014-05-12 07:34:14

标签: winapi exception-handling

在尝试弄清楚为什么我正在处理的应用程序无法关闭时,我意识到它在WM_CLOSE处理程序中抛出异常。但是,不是应用程序崩溃(应该如此),异常会被忽略。

为了确保没有其他事情发生,我在Visual Studio中创建了一个新的C ++ Win32应用程序并添加了这个:

case WM_CLOSE:
    (*(int*)NULL) = 0;
    break;

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

所以我很好奇:WM_CLOSE有什么特别之处让Windows认为应该吞下它所引发的异常?

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

1 个答案:

答案 0 :(得分:2)

Win 64上WindowProc吞下的异常是预期的行为。 (See docs。)

,请参阅Paul Betts'博客上的更好解释,尤其是他的说明

  

为什么这不会一直发生?

     

这就是为什么这似乎只发生在某些窗口消息上 -   请记住,窗口消息可以来自不同的来源,   任何人(*)都可以将消息排队到窗口。但是,某些窗口   消息直接通过win32k.sys发送(最值得注意的是   WM_CREATE)作为用户模式调用的直接同步结果。

似乎对这个问题有所了解。

Random ASCII also对所有这些内核模式 - 吞咽行为有一些很好的解释:

  

未能完全停止

     

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

     

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

     

64位Windows的引入很复杂。在64位Windows上   不可能跨越内核边界展开堆栈。也就是说,如果...在回调中抛出异常,那就是   应该在内核边界的另一边处理   Windows无法处理此问题。

     

这可能看起来有点深奥且不太可能 - 编写内核回调   似乎是一种罕见的活动 - 但它实际上很常见。在   特别是, WindowProc 是一个回调,通常是来调用   内核,......

作为奖励:见here on SO on the why