为了testing这个问题,我写了一个最小的Windows应用程序。 如果我在WM_PAINT
处理程序中强制访问冲突,这个exception永远不会到达debugging器。 如果在没有debugging器的情况下启动,访问冲突也不会显示出来。 通常你应该得到Windows错误报告对话框。
深入挖掘看来,user32.dll中的某些内容会捕获所有传入的exception。 这是正常的行为? 我能不能控制这个? 没有捕获所有的例外安全风险? 至less这是讨厌的地狱。
这是Vista 64和32位和64位应用程序。在XP上,exception似乎按预期处理。 其他Windows消息也有同样的问题。 也许他们都是?
WM_PAINT
处理程序:
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); *(int*)0 = 0; EndPaint(hWnd, &ps); break;
作为一种解决方法,我删除我的窗口过程中的所有注册的异常处理程序。 相当丑陋。
LRESULT CALLBACK window_proc( HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { //获取线程信息块 NT_TIB * tib; __asm { mov EAX,FS:[18h] mov [tib],EAX } //旧的异常处理程序列表 _EXCEPTION_REGISTRATION_RECORD * old_exception_handler = tib-> ExceptionList; //除了默认处理程序之外,移除所有异常处理程序 while(tib-> ExceptionList-> Next!=(_EXCEPTION_REGISTRATION_RECORD *) - 1){ tib-> ExceptionList = tib-> ExceptionList-> Next; } LRESULT结果= DefWindowProc(hwnd,uMsg,wParam,lParam); //恢复旧的异常处理程序 tib-> ExceptionList = old_exception_handler; 返回结果; }
这是一个已知的缺陷。 检查修补程序。 http://support.microsoft.com/kb/976038
DispatchMessage似乎现在包含一个SEH try catch块,它禁止window procs生成的异常。
您仍然可以在调试器中捕获这些异常 – 取决于您的Visual Studio版本,您需要打开调试 – >异常对话框,并勾选所有Win32异常的“中断时抛出异常”列,或至少异常0xc0000005
在WinXP和Vista中将抛出异常。 我刚刚在Vista中调试和发布配置。 新的Win32应用程序项目中是否有同样的问题?
我注意到,当你启用了Aero(这在Vista中是默认的)时,调整窗口大小会导致许多页面错误。 这些并不是正常的虚拟内存需要分页错误。 我怀疑(尽管这只是一个理论),Aero将图形输出重定向到受保护的内存块,并捕获故障,以便知道桌面上需要重新组合可见表面的哪些位。 也许这也是吃其他访问违规。
从XP开始,可以使用Vector Exception Handling功能。 它优先于所有其他类型的例外。 在我的例子中,它正确地捕获了WM_PAINT消息中的访问冲突。 不幸的是,它也捕获所有其他类型的异常,我应该通过检查异常代码来解决这个异常。