windows Windows静默捕获异常,如何手动处理?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2622200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Exceptions silently caught by Windows, how to handle manually?
提问by Mark Ingram
We're having problems with Windows silently eating exceptions and allowing the application to continue running, when the exception is thrown inside the message pump. For example, we created a test MFC MDI application, and overrode OnDraw:
当异常在消息泵中抛出时,我们遇到了 Windows 静默处理异常并允许应用程序继续运行的问题。例如,我们创建了一个测试 MFC 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
}
You would expect a nasty error message when running the application, but you actually get nothing at all. The program appears to be running perfectly well, but if you check the output window you will see:
运行应用程序时,您可能会看到令人讨厌的错误消息,但实际上什么也没得到。该程序似乎运行良好,但如果您检查输出窗口,您将看到:
First-chance exception at 0x13929384 in Test.exe: 0xC0000005: Access violation writing location 0x00000000.
First-chance exception at 0x77c6ee42 in Test.exe: 0xC0150010: The activation context being deactivated is not active for the current thread of execution.
Test.exe 中 0x13929384 处的第一次机会异常:0xC0000005:访问冲突写入位置 0x00000000。
Test.exe 中 0x77c6ee42 处的第一次机会异常:0xC0150010:被停用的激活上下文对于当前执行线程未激活。
I know why I'm receiving the application context exception, but why is it being handled silently? It means our applications could be suffering serious problems when in use, but we'll never know about it, because our users will never report any problems.
我知道为什么我会收到应用程序上下文异常,但为什么它会被静默处理?这意味着我们的应用程序在使用时可能会遇到严重的问题,但我们永远不会知道,因为我们的用户永远不会报告任何问题。
采纳答案by Mark Ingram
After browsing similar questions I stumbled across this answer: OpenGL suppresses exceptions in MFC dialog-based application
在浏览了类似的问题后,我偶然发现了这个答案: OpenGL 在基于 MFC 对话框的应用程序中抑制异常
"Ok, I found out some more information about this. In my case it's windows 7 that installs KiUserCallbackExceptionHandler as exception handler, before calling my WndProc and giving me execution control. This is done by ntdll!KiUserCallbackDispatcher. I suspect that this is a security measure taken by Microsoft to prevent hacking into SEH.
The solution is to wrap your wndproc (or hookproc) with a try/except frame."
“好的,我发现了更多关于此的信息。在我的情况下,Windows 7 安装 KiUserCallbackExceptionHandler 作为异常处理程序,然后调用我的 WndProc 并给我执行控制权。这是由 ntdll!KiUserCallbackDispatcher 完成的。我怀疑这是一种安全微软为防止黑客入侵 SEH 所采取的措施。
解决方案是用 try/except 框架包装 wndproc(或 hookproc)。”
I've filed a bug report with Microsoft, you can see their response here:
http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages
我已向 Microsoft 提交了错误报告,您可以在此处查看他们的回复:http:
//connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught -in-wndproc-消息
From Microsoft:
来自微软:
Thanks for the report. I've found out that this is a Windows issue, and there is a hot fix available. Please see http://support.microsoft.com/kb/976038for a fix that you can install if you wish.
谢谢你的报告。我发现这是一个 Windows 问题,并且有可用的修补程序。请参阅 http://support.microsoft.com/kb/976038以获取可根据需要安装的修复程序。
回答by Simon Hofverberg
If you're running on an x64 OS you may have been bitten by this:
如果您在 x64 操作系统上运行,您可能会被这个问题困扰:
Or (less likely in this case), it may be this: http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx
或者(在这种情况下不太可能),可能是这样的:http: //blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx
回答by Brian
I experienced this same issue, and found it was a result of this Microsoft bug: http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages
我遇到了同样的问题,发现这是微软错误的结果:http: //connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught -in-wndproc-消息
There's a fix available from Microsoft, though deploying it is somewhat challenging if you have multiple target platforms:
Microsoft 提供了一个修复程序,但如果您有多个目标平台,部署它会有些挑战性:
http://support.microsoft.com/kb/976038
http://support.microsoft.com/kb/976038
Here's an article on the subject describing the behavior:
这是一篇关于描述行为的主题的文章:
The issue is basically that Hardware exceptions in 32-bit programs are silently caught in the WndProc routine on 64-bit OSs, unless you send commands telling it not to. Microsoft has a hotfix for the issue that isrequired if you're running Vista SP2, but isn't required with Windows 7 SP1 (not sure about Win7 without the SP).
问题基本上是 32 位程序中的硬件异常在 64 位操作系统上的 WndProc 例程中被静默捕获,除非您发送命令告诉它不要。微软在该问题的修补程序是,如果你使用的是Vista SP2必需的,但与Windows 7 SP1(不含SP不知道Win7的)不是必需的。
Even WITH the hotfix, you need to enable the correct behavior by setting a registry key or making some calls to the kernel to tell it your process expects hardware exceptions to crash when encountered during WndProc.
即使使用修补程序,您也需要通过设置注册表项或对内核进行一些调用来启用正确的行为,以告诉它您的进程在 WndProc 期间遇到硬件异常时会崩溃。
According to the PaulBetts link above, this was done for backwards compatibility with Windows Server 2003.
根据上面的 PaulBetts 链接,这样做是为了向后兼容 Windows Server 2003。
If you program is a 64-bit program, this issue goes away.
如果您的程序是 64 位程序,这个问题就会消失。
回答by SteelBytes
functions that may be of interest:
可能感兴趣的功能:
SetUnhandledExceptionFilter()
_set_invalid_parameter_handler()
_RTC_SetErrorFuncW()
_CrtSetReportHookW2()
PS, be aware that SetUnhandledExceptionFilter() can be overriden by other dlls loaded into your .exe. eg, flash and nvidia direct3d do this. I use api hooking to cure this.
PS,请注意 SetUnhandledExceptionFilter() 可以被加载到您的 .exe 中的其他 dll 覆盖。例如,flash 和 nvidia direct3d 就是这样做的。我使用 api hooking 来解决这个问题。
回答by David
ANSWER IN HINDSIGHT for anyone who stumbles upon this later.
对于后来偶然发现的任何人,事后回答。
This was caused by a known issue in Windows http://support.microsoft.com/kb/976038- make sure you're up to date, install the hotpatch if you need to, and mark your application as Windows 7 compatible. http://msdn.microsoft.com/en-us/library/dd371711%28v=vs.85%29.aspx
这是由 Windows http://support.microsoft.com/kb/976038 中的一个已知问题引起的- 确保您是最新的,如果需要安装热补丁,并将您的应用程序标记为与 Windows 7 兼容。http://msdn.microsoft.com/en-us/library/dd371711%28v=vs.85%29.aspx
I've seen this with exception codes c015000f and c0150010.
我已经看到异常代码 c015000f 和 c0150010。
回答by Alessandro Jacopson
You can force Windows to not ignore the exceptions with this code snippet (from Microsoft's Exceptions that are thrown from an application that runs in a 64-bit version of Windows are ignored) that you will put in your process code:
您可以使用以下代码片段强制 Windows 不忽略异常(来自 Microsoft 的从在 64 位版本的 Windows 中运行的应用程序抛出的异常被忽略),您将放入您的进程代码中:
// 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);
}
}
It may be you have to add also an unhandled exception filter: the filter acts like a "top level exception handler" that is like a topmost catch
block. For extracting a programmer-friendly string from _EXCEPTION_POINTERS you can see Is there a function to convert EXCEPTION_POINTERS struct to a string?
您可能还必须添加一个未处理的异常过滤器:过滤器就像一个“顶级异常处理程序”,就像一个最顶层的catch
块。为了从 _EXCEPTION_POINTERS 中提取程序员友好的字符串,您可以看到是否有将 EXCEPTION_POINTERS 结构转换为字符串的函数?
LONG WINAPI my_filter(_In_ struct _EXCEPTION_POINTERS *ExceptionInfo)
{
::OutputDebugStringA("an exception occured!");
return EXCEPTION_EXECUTE_HANDLER;
}
You add the filter with:
您添加过滤器:
::SetUnhandledExceptionFilter(my_filter);
and you have to do it in every threads of your process: while the previous snippet is per-process, the filter is per-thread.
并且您必须在进程的每个线程中执行此操作:虽然前面的代码段是每个进程的,但过滤器是每个线程的。
回答by Simon Linder
Your output looks like you're using Visual Studio...
If not forget about my answer.
You can specify which exceptions will be thrown normally, meaning that Visual Studio catches them and your progam stops where the access violation occurred. Do this in the Debug/Exceptions... menu. If you are not sure what to enable, just enable them all...
您的输出看起来像是在使用 Visual Studio...
如果没有忘记我的回答。
您可以指定哪些异常将被正常抛出,这意味着 Visual Studio 会捕获它们并且您的程序在发生访问冲突的地方停止。在调试/异常...菜单中执行此操作。如果您不确定要启用什么,只需启用它们...