为什么在win32计时器回调中抛出未处理的异常不会被调试器视为未处理的异常?

Dou*_* T. 3 c++ winapi exception

我一直在追踪工作中一个非常阴险的错误.似乎导致我一直在跟踪的非常奇怪的行为的事件似乎是在处理计时器回调时抛出的异常.异常不是由我的任何代码处理的,因此我希望调试器会收到未处理异常的通知,并提醒我一个不错的弹出窗口.不,相反,"第一次机会"异常消息会追溯到调试器,并且所有内容都会静默移动.

我写了以下程序来演示这个问题:

#include "stdafx.h"
#include <Windows.h>

class FooExcept
{
};

VOID CALLBACK Timer(HWND hwnd,
    UINT uMsg,
    UINT_PTR idEvent,
    DWORD dwTime)
{
    printf("Here\n");
    throw FooExcept();
    printf("Also Here\n");
}


int _tmain(int argc, _TCHAR* argv[])
{
    SetTimer(0, 0, 1000, Timer);

    int bRet;
    HWND hWnd;
    MSG msg;
    // Standard Win32 message pump
    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    { 
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此程序到Visual Studio输出窗口的输出是重复的:

First-chance exception at 0x76dbb9bc in TimerTest.exe: Microsoft C++ exception: FooExcept at memory location 0x0034f743..

当然,我的项目更加复杂,并且正在向调试器打印出大量的TRACE信息.第一次机会异常很容易在输出中丢失.

然而

那不是我关心的问题.这显然是一个例外我不处理.Windows是否偷偷地决定为我处理这个问题?为什么?如果没有,为什么不给我一个明确的弹出窗口警告我未处理的异常?这样的弹出窗口可以节省我几天的调试时间.

XP/VS 2008和Win7/VS 2010之间的这种行为似乎是一致的.

bro*_*ekk 7

在Windows 7 SP1中,这已在某种程度上得到修复(见下文).

在文章http://support.microsoft.com/kb/976038中,您会发现有关错误修正的说明以及如何使用它来禁用此行为的说明.你必须要么:

  • 在注册表中设置进程选项或
  • 呼叫功能SetProcessUserModeExceptionPolicy导出kernel32.dll

我已在Win7和WS08R2 SP1.xls的更新中验证了此错误修复确实包含在Windows 7 Service Pack 1中,因此您所要做的就是启用它(假设您已经安装了Windows 7 SP1).

至于解释为什么这样做,我们可以猜测一些不明智的尝试,以防止遗留应用程序以向后兼容性的名义崩溃.

  • PS(不是答案的真正部分)我在这个主题http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disaringaring上找到了这个大而完整的博客文章-onload-异常用户模式回调的例外 - 在-64 / (2认同)