OpenGL 抑制基于 MFC 对话框的应用程序中的异常

我有一个使用 MSVS2005 创建的 MFC 驱动的基于对话框的应用程序.这是我的问题一步一步.我的对话框和相应的点击处理程序上有按钮,代码如下:

I have an MFC-driven dialog-based application created with MSVS2005. Here is my problem step by step. I have button on my dialog and corresponding click-handler with code like this:

int* i = 0;
*i = 3;

我正在运行调试版本的程序,当我单击按钮时,Visual Studio 捕捉焦点并警告访问冲突写入位置"异常,程序无法从错误中恢复,我所能做的就是停止调试.这是正确的行为.

I'm running debug version of program and when I click on the button, Visual Studio catches focus and alerts "Access violation writing location" exception, program cannot recover from the error and all I can do is to stop debugging. And this is the right behavior.

现在我在 OnInitDialog() 方法中添加一些 OpenGL 初始化代码:

Now I add some OpenGL initialization code in the OnInitDialog() method:

    HDC DC = GetDC(GetSafeHwnd());
    static PIXELFORMATDESCRIPTOR pfd =
    {
      sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
      1, // version number
      PFD_DRAW_TO_WINDOW | // support window
      PFD_SUPPORT_OPENGL | // support OpenGL
      PFD_DOUBLEBUFFER, // double buffered
      PFD_TYPE_RGBA, // RGBA type
      24, // 24-bit color depth
      0, 0, 0, 0, 0, 0, // color bits ignored
      0, // no alpha buffer
      0, // shift bit ignored
      0, // no accumulation buffer
      0, 0, 0, 0, // accum bits ignored
      32, // 32-bit z-buffer
      0, // no stencil buffer
      0, // no auxiliary buffer
      PFD_MAIN_PLANE, // main layer
      0, // reserved
      0, 0, 0 // layer masks ignored
    };

    int pixelformat = ChoosePixelFormat(DC, &pfd);
    SetPixelFormat(DC, pixelformat, &pfd);

    HGLRC hrc = wglCreateContext(DC);
    ASSERT(hrc != NULL);
    wglMakeCurrent(DC, hrc);

当然,这不完全是我所做的,它是我的代码的简化版本.那么现在奇怪的事情开始发生:所有初始化都很好,OnInitDialog() 中没有错误,但是当我单击按钮时......没有抛出异常.没发生什么事.完全没有.如果我在 *i = 3; 处设置断点并在其上按 F11,则处理程序函数会立即停止并将焦点返回到应用程序,该应用程序继续正常工作.我可以再次单击按钮,同样的事情会发生.

Of course this is not exactly what I do, it is the simplified version of my code. Well now the strange things begin to happen: all initialization is fine, there are no errors in OnInitDialog(), but when I click the button... no exception is thrown. Nothing happens. At all. If I set a break-point at the *i = 3; and press F11 on it, the handler-function halts immediately and focus is returned to the application, which continue to work well. I can click button again and the same thing will happen.

似乎有人已经处理了发生的访问冲突异常,并默默地将执行返回到主应用程序消息接收周期.

It seems like someone had handled occurred exception of access violation and silently returned execution into main application message-receiving cycle.

如果我注释 wglMakeCurrent(DC, hrc); 行,一切正常,抛出异常,Visual Studio 捕获它并显示带有错误消息的窗口,之后必须终止程序.

If I comment the line wglMakeCurrent(DC, hrc);, all works fine as before, exception is thrown and Visual Studio catches it and shows window with error message and program must be terminated afterwards.

我在安装了网站上提供的最新驱动程序(2010 年 1 月 11 日)的 Windows 7 64 位、NVIDIA GeForce 8800 下遇到了这个问题.我的同事使用的是 32 位 Windows Vista 并且没有这样的问题 - 在这两种情况下都会引发异常并且应用程序崩溃.

I experience this problem under Windows 7 64-bit, NVIDIA GeForce 8800 with latest drivers (of 11.01.2010) available at website installed. My colleague has Windows Vista 32-bit and has no such problem - exception is thrown and application crashes in both cases.

好吧,希望好人能帮助我:)

Well, hope good guys will help me :)

PS 问题最初发布在 this 主题.

PS The problem originally where posted under this topic.

推荐答案

好的,我找到了更多关于这个的信息.在我的情况下,Windows 7 安装 KiUserCallbackExceptionHandler 作为异常处理程序,然后调用我的 WndProc 并给我执行控制权.这是由 ntdll!KiUserCallbackDispatcher 完成的.我怀疑这是微软为防止黑客入侵 SEH 而采取的安全措施.

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.

解决方案是使用 try/except 框架包装您的 wndproc(或 hookproc),以便您可以在 Windows 之前捕获异常.

The solution is to wrap your wndproc (or hookproc) with a try/except frame so you can catch the exception before Windows does.

感谢 http://www.nynaeve.net/

我们已经就此事联系了 nVidia问题,但他们说这不是他们的bug,而是微软的.可以请告诉您您是如何找到异常处理程序?你有吗一些附加信息,例如一些来自微软的反馈?

We've contacted nVidia about this issue, but they say it's not their bug, but rather the Microsoft's. Could you please tell how you located the exception handler? And do you have some additional information, e.g. some feedbacks from Microsoft?

我使用 WinDbg 中的!exchain"-命令来获取此信息.

I used the "!exchain"-command in WinDbg to get this information.

相关文章