WndProc 中的 64 位异常默默失败

发布于 2024-08-28 08:25:37 字数 1332 浏览 10 评论 0原文

以下代码在 Windows 7 32 位下运行时会出现硬故障:

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
}

但是,如果我在 Windows 7 64 位上尝试此操作,我只会在输出窗口中看到以下内容:

0x13929384处的第一次机会异常 在 Test.exe 中:0xC0000005:访问 违规写入位置 0x00000000。
0x77c6ee42 处的第一次机会异常 在Test.exe中:0xC0150010: 激活上下文被停用 对于当前线程不活跃 执行。

这是什么原因呢?我知道这是硬件异常(http://msdn.microsoft.com/en -us/library/aa363082.aspx),但是为什么在32位和64位下运行时有差异?我该如何正确处理此类错误?因为它们确实应该被捕获和修复,而不是当前发生的情况,即 Windows 只是向应用程序发送消息并让它运行(因此用户和开发人员完全不知道实际发生了任何问题)。

更新: 我们的常规崩溃报告软件使用 SetUnhandledExceptionFilter 但在 x64 上不会针对 WndProc 内的硬件异常调用该函数。有人有这方面的信息或解决方法吗?

更新2: 我已在 Microsoft Connect 上报告了该问题:
https://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

The following code will give a hard fail when run under Windows 7 32bit:

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
}

However, if I try this on Windows 7 64bit, I just get this in the output window:

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.

What is the reason for this? I know it's a hardware exception (http://msdn.microsoft.com/en-us/library/aa363082.aspx), but why the difference when ran under 32bit and 64bit? And what can I do to correctly handle these kind of errors? Because they should really be trapped and fixed, as opposed to what currently happens which is Windows just carries on pumping messages to the application and let's it run (so the user and the developers are completely unaware any problems have actually occurred).

Update:
Our regular crash reporting software uses SetUnhandledExceptionFilter but that doesn't get called on x64 for hardware exceptions inside a WndProc. Does anyone have any information on this, or a workaround?

Update2:
I've reported the issue at Microsoft Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小耗子 2024-09-04 08:25:37

当因访问冲突异常而展开堆栈时,会引发另一个异常。它被吞噬,导致 AV 消失。您需要找出执行此操作的代码。调试 + 异常,选中“Win32 异常”的“抛出”框。调试器将在第一个处停止,然后继续。当它再次停止时检查调用堆栈。如果您无法弄清楚,请将其添加到您的问题中。

There's another exception being raised while the stack is being unwound for the Access Violation exception. Which is being swallowed, causing the AV to disappear. You'll need to find out what code is doing this. Debug + Exceptions, check the Thrown box for Win32 Exceptions. The debugger will stop on the first one, continue. Check out the call stack when it stop again. Add it to your question if you can't figure it out.

无悔心 2024-09-04 08:25:37

好的,我已经收到微软的回复:

你好,

感谢您的报告。我发现了
这是一个 Windows 问题,并且
有一个可用的热修复。请

http://support.microsoft.com/kb/976038
如果您可以安装修复程序
愿望。

@Skute:请注意该程序
兼容性助手会询问一次
如果程序应该被允许
继续执行,之后就
总是被允许的,所以这可能是
令人困惑的行为的原因
你正在看到。

Pat Brenner Visual C++ 库
发展

因此,解决方法是确保安装了修补程序,或者使用 __try / __ except 块将应用程序中的每个 WndProc 包装起来。

OK, I've received a reply from Microsoft:

Hello,

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/976038
for a fix that you can install if you
wish.

@Skute: note that the Program
Compatibility Assistant will ask once
if the program should be allowed to
continue to execute, and after that it
will always be allowed, so that may be
the cause of the confusing behavior
you are seeing.

Pat Brenner Visual C++ Libraries
Development

So the workaround is either make sure the hotfix is installed, or wrap each WndProc in your application with a __try / __except block.

爱格式化 2024-09-04 08:25:37

我们设法解决此问题的唯一方法是在应用程序中的每个 WndProc 回调周围放置 __try / __ except 。然后我们将异常路由到异常处理程序。可怕的是,但看起来这是 Windows 本身的问题。仍在等待微软回复我们。

The only way we've managed to work around this problem is to put a __try / __except around each WndProc callback in the application. We then route the exception to our exception handler. Horrible, but looks like it's a problem with Windows itself. Still waiting on Microsoft to get back to us.

撕心裂肺的伤痛 2024-09-04 08:25:37

我大胆猜测这个问题实际上与 SEH 在 x64 中的工作方式有关。如果在堆栈展开时您的异常必须通过内核模式返回,那么您所遇到的就是设计行为: OnLoad异常消失的案例 。 Windows 正在为您“处理”您的异常;该热修复是一种解决方法,可以使特定的 x64 应用程序像 x86 一样崩溃。

I would venture a guess that the problem is actually related to how SEH works in x64. If your exception has to go back up through kernel-mode while the stack is unwinding, then what you're stuck with is by-design behavior: The case of the disappearing OnLoad exception. Windows is "handling" your exception for you; the hot-fix is a workaround to make specific x64 apps crash just like x86 does.

半葬歌 2024-09-04 08:25:37

我做了一些功课来找到这个:
异常被windows捕获。以下是堆栈和反汇编:

当 wndproc 被调用时堆栈和反汇编

I did some homework to find this:
the exception is caught by windows. Here are stacks and disassembling:

stack and disassembling when wndproc get called

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文