WM_PAINT中的访问冲突未被捕获

时间:2009-09-28 16:17:28

标签: c++ windows exception winapi access-violation

为了测试这个问题,我编写了一个最小的Windows应用程序。如果我在WM_PAINT处理程序中强制执行访问冲突,则此异常永远不会进入调试器。如果在没有调试器的情况下启动,则访问冲突也不会显示。通常,您应该获得Windows错误报告对话框。

深入挖掘似乎user32.dll中的某些内容会捕获所有传入的异常。这是正常的行为吗?我可以以某种方式控制它吗?是不是将所有异常都列为安全风险?至少它很烦人。

这是Vista 64上的32位和64位应用程序。在XP上,异常似乎按预期处理。其他Windows消息也有同样的问题。也许所有这些?

WM_PAINT处理程序:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    *(int*)0 = 0;
    EndPaint(hWnd, &ps);
    break;

6 个答案:

答案 0 :(得分:5)

作为一种解决方法,我在窗口过程中删除所有已注册的异常处理程序。相当难看。

LRESULT CALLBACK window_proc( 
    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    // get thread information block
    NT_TIB* tib;
    __asm {
        mov EAX, FS:[18h]
        mov [tib], EAX
    }
    // old exception handler list
    _EXCEPTION_REGISTRATION_RECORD* old_exception_handler = tib->ExceptionList;
    // remove all exception handler with exception of the default handler
    while( tib->ExceptionList->Next != (_EXCEPTION_REGISTRATION_RECORD*)-1 ) {
        tib->ExceptionList = tib->ExceptionList->Next;
    }

    LRESULT result = DefWindowProc( hwnd, uMsg, wParam, lParam );

    // restore old exception handler
    tib->ExceptionList = old_exception_handler;

    return result;
}

答案 1 :(得分:5)

这是一个已知的缺陷。检查此修补程序。 http://support.microsoft.com/kb/976038

答案 2 :(得分:3)

DispatchMessage现在似乎包含一个SEH try catch块,它禁止窗口过程产生的异常。

您仍然可以在调试器中捕获这些异常 - 取决于您打开debug-> exceptions对话框所需的visual studio版本,并勾选所有Win32异常的“抛出异常时断开”列,或者至少异常0xc0000005

答案 3 :(得分:0)

在WinXP和Vista中会抛出异常。我刚刚在Vista的Debug和Release配置中对此进行了测试。您是否在新的Win32应用程序项目中遇到同样的问题?

答案 4 :(得分:0)

我注意到,当您启用Aero(默认情况下在Vista中)时,调整窗口大小往往会产生许多页面错误。这些也不是正常的虚拟内存需要分页故障。我怀疑(虽然这只是一个理论),Aero将图形输出重定向到受保护的内存块,并捕获故障以便知道需要在桌面上重新组合可见表面的哪些位。也许这也正在侵犯其他访问权限。

答案 5 :(得分:0)

从XP开始,可以使用矢量异常处理功能。它优先于所有其他类型的例外。在我的示例中,它正确捕获了WM_PAINT消息中的访问冲突。不幸的是,它还捕获了所有其他类型的异常,我应该通过检查异常代码来解决这些异常。