在尝试弄清楚为什么我正在处理的应用程序无法关闭时,我意识到它在WM_CLOSE
处理程序中抛出异常。但是,不是应用程序崩溃(应该如此),异常会被忽略。
为了确保没有其他事情发生,我在Visual Studio中创建了一个新的C ++ Win32应用程序并添加了这个:
case WM_CLOSE:
(*(int*)NULL) = 0;
break;
同样的事情:没有崩溃,只是调试日志中的第一次机会异常。如果我将相同的代码添加到WM_COMMAND
处理程序,它会按预期崩溃。
所以我很好奇:WM_CLOSE
有什么特别之处让Windows认为应该吞下它所引发的异常?
(顺便说一下:这是在Windows 7 x64上,运行x86程序)
答案 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。