我们遇到了Windows的问题,静静地吃着exception,并允许应用程序继续运行,当exception在消息泵中抛出时。 例如,我们创build了一个testingMFC MDI应用程序,并且覆盖了OnDraw:
void CTestView::OnDraw(CDC* /*pDC*/) { *(int*)0 = 0; // Crash CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: add draw code for native data here }
运行应用程序时,您会期望出现一个令人讨厌的错误消息,但实际上什么都没有得到。 该程序似乎运行得非常好,但如果你检查输出窗口,你会看到:
Test.exe中0x13929384的第一次机会exception:0xC0000005:访问冲突写入位置0x00000000。
Test.exe中0x77c6ee42的第一次机会exception:0xC0150010:当前正在执行的线程未激活正在激活的激活上下文。
我知道为什么我收到应用程序上下文exception,但为什么它被默默处理? 这意味着我们的应用程序在使用时可能会遇到严重的问题,但我们永远不会知道,因为我们的用户永远不会报告任何问题。
如果您在x64操作系统上运行,您可能会被这个问题困扰:
或者(在这种情况下可能性较小),可能是这样的: http : //blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx
在浏览类似的问题后,我偶然发现了这个答案: OpenGL在MFC基于对话框的应用程序中抑制异常
“好的,我发现了更多关于这个的信息,在我的情况下,它是安装KiUserCallbackExceptionHandler作为异常处理程序的Windows 7,在调用我的WndProc并给予执行控制权之前,这是由ntdll!KiUserCallbackDispatcher完成的,我怀疑这是一个安全微软为防止黑客进入SEH而采取的措施。
解决方法是用你的wndproc(或者hookproc)包装一个try / except帧。
我已经向微软提交了一个错误报告,你可以在这里看到他们的回应:
http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages
来自微软:
感谢您的报告。 我发现这是一个Windows问题,并有一个可用的修复程序。 请参阅http://support.microsoft.com/kb/976038以获得可以根据需要安装的修复程序。
可能感兴趣的功能:
SetUnhandledExceptionFilter() _set_invalid_parameter_handler() _RTC_SetErrorFuncW() _CrtSetReportHookW2()
PS,请注意,SetUnhandledExceptionFilter()可以被加载到您的.exe中的其他dll重写。 例如,闪存和NVIDIA Direct3D做到这一点。 我使用API钩来治愈这个。
我遇到了同样的问题,并发现这是由于这个微软的bug: http : //connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught -in-的WndProc的消息
Microsoft提供了一个修补程序,但是如果您有多个目标平台,则部署它有点具有挑战性:
http://support.microsoft.com/kb/976038
这里是关于这个主题描述行为的文章:
问题基本上是32位程序中的硬件异常在64位操作系统上的WndProc例程中默默地捕获,除非您发送命令告诉它不要。 如果您运行的是Vista SP2,则Microsoft需要使用此修复程序,但Windows 7 SP1不需要该修复程序(不知道没有SP的Win7)。
即使使用修补程序,也需要通过设置注册表项或调用内核来启用正确的行为,以告知您的进程在WndProc期间遇到硬件异常崩溃。
根据上面的PaulBetts链接,这是为了向后兼容Windows server 2003而完成的。
如果你的程序是一个64位的程序,这个问题就消失了。
对于任何后来遇到这种情况的人来说,
这是由Windows中的一个已知问题引起的http://support.microsoft.com/kb/976038 – 确保您是最新的,如果需要的话安装hotpatch,并将您的应用程序标记为Windows 7兼容。 http://msdn.microsoft.com/en-us/library/dd371711%28v=vs.85%29.aspx
我看过这个例外代码c015000f和c0150010。
您可以强制Windows不要忽略这些代码片段(从忽略在64位版本的Windows中运行的应用程序抛出的 Microsoft 异常)中的异常,这些异常将放入进程代码中:
// my SDK is v6.0A and the two APIs are not available in the .h files, so I need to get them at runtime #define PROCESS_CALLBACK_FILTER_ENABLED 0x1 typedef BOOL (WINAPI *GETPROCESSUSERMODEEXCEPTIONPOLICY)(__out LPDWORD lpFlags); typedef BOOL (WINAPI *SETPROCESSUSERMODEEXCEPTIONPOLICY)(__in DWORD dwFlags ); HINSTANCE h = ::LoadLibrary(L"kernel32.dll"); if ( h ) { GETPROCESSUSERMODEEXCEPTIONPOLICY GetProcessUserModeExceptionPolicy = reinterpret_cast< GETPROCESSUSERMODEEXCEPTIONPOLICY >( ::GetProcAddress(h, "GetProcessUserModeExceptionPolicy") ); SETPROCESSUSERMODEEXCEPTIONPOLICY SetProcessUserModeExceptionPolicy = reinterpret_cast< SETPROCESSUSERMODEEXCEPTIONPOLICY >( ::GetProcAddress(h, "SetProcessUserModeExceptionPolicy") ); if ( GetProcessUserModeExceptionPolicy == 0 || SetProcessUserModeExceptionPolicy == 0 ) { return; } DWORD dwFlags; if (GetProcessUserModeExceptionPolicy(&dwFlags)) { SetProcessUserModeExceptionPolicy(dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED); } }
这可能是你还必须添加一个未处理的异常过滤器 :过滤器就像一个“顶级异常处理程序”就像一个最上面的catch
块。 为了从_EXCEPTION_POINTERS提取一个程序员友好的字符串,你可以看到是否有一个函数将EXCEPTION_POINTERS结构转换为字符串?
LONG WINAPI my_filter(_In_ struct _EXCEPTION_POINTERS *ExceptionInfo) { ::OutputDebugStringA("an exception occured!"); return EXCEPTION_EXECUTE_HANDLER; }
您添加过滤器:
::SetUnhandledExceptionFilter(my_filter);
而且你必须在你的进程的每个线程中执行它:当前面的代码片段是per-process时,过滤器是每个线程的。
你的输出看起来像你正在使用Visual Studio …
如果不忘记我的答案。
您可以指定哪些异常将被正常抛出,这意味着Visual Studio捕获它们,并且您的程序停止发生访问冲突。 在Debug / Exceptions …菜单中执行此操作。 如果您不确定要启用什么,只需启用它们即可