【发布时间】:2014-05-12 07:34:13
【问题描述】:
在试图弄清楚为什么我正在开发的应用程序无法关闭时,我意识到它在其WM_CLOSE 处理程序中引发了异常。然而,该异常并没有崩溃(应该如此),而是被默默地忽略了。
为了确保没有其他事情发生,我在 Visual Studio 中创建了一个新的 C++ Win32 应用并添加了以下内容:
case WM_CLOSE:
(*(int*)NULL) = 0;
break;
同样的事情:没有崩溃,只是调试日志中的第一次机会异常。如果我将相同的代码添加到 WM_COMMAND 处理程序,它会按预期崩溃。
所以我很好奇:WM_CLOSE 有什么特别之处,以至于 Windows 认为应该吞噬它抛出的异常?
(顺便说一句:这是在 Windows 7 x64 上,运行 x86 程序)
【问题讨论】:
-
WM_CLOSE本身并没有什么特别之处。通过在__try/__except处理程序下调用WndProc,您的WndProc回调中未处理的异常总是被静默忽略。这是唯一安全的实现,因为when you transfer control across stack frames, all the frames in between need to be in on the joke。 -
默认情况下,WindoWProcedure 调用destroy window 来销毁窗口。这可能是任何异常都被重定向到“/dev/null”的原因:msdn.microsoft.com/en-us/library/windows/desktop/… 和 msdn.microsoft.com/en-us/library/windows/desktop/…
-
@IInspectable,我不认为 Raymond Chen 说
WndProc回调在他的文章中受到保护。实际上看起来他说的是相反的:As a result of this overall mindset, Win32 code doesn't worry too much about recovering from exceptions. If an exception happens, then it means your process is already toast and there's no point trying to fix it。此外,如果回调受到保护,则 NULL 指针取消引用也不会在WM_COMMAND处理程序中崩溃。 -
@Brad 如果您不想让您的异常被吞下,您需要为您的应用程序提供一个与 Win7 兼容的清单,并编译为 64 位。否则,“旧”的 Win2k3 行为会生效,它会吞下异常。
-
@Brad 拥有有效的 Windows 7 清单足以改变行为。这在The case of the disappearing OnLoad exception 中有详细说明。我应该更准确一点:并非所有异常都默认被吞下,但只有那些
WndProc是内核函数的用户模式回调(例如WM_CREATE/WM_NCCREATE作为调用CreateWindow的结果) )。