2010-01-29 62 views
5

我有一个使用MSVS2005创建的MFC驱动的基于对话框的应用程序。这是我的问题一步一步来。我有我的对话和相应的点击处理程序按钮,这样的代码:OpenGL在MFC基于对话框的应用程序中抑制异常

int* i = 0; 
*i = 3; 

我正在运行的程序的调试版本,当我按一下按钮,Visual Studio的捕捞重点和警报“访问冲突写入位置“例外,程序无法从错误中恢复,我所能做的就是停止调试。这是正确的行为。

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

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,处理函数立即停止,焦点返回到应用程序,继续运行良好。我可以再次点击按钮,同样的事情会发生。

看起来好像有人已经处理了发生访问冲突的异常并默默地将执行返回到主应用程序的消息接收周期。

如果我评论行wglMakeCurrent(DC, hrc);,所有的工作都像以前一样正常,抛出异常并且Visual Studio捕获它并显示带有错误消息的窗口,并且之后程序必须终止。

我在安装了网站的Windows 7 64位,NVIDIA GeForce 8800和最新驱动程序(11.01.2010)下遇到此问题。我的同事拥有32位的Windows Vista,并且没有这样的问题 - 在这两种情况下都会抛出异常并导致应用程序崩溃。

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

PS的问题最初是在那里下this主题贴。

+0

这很有趣,我最近有同样的问题......如果你在一个try-catch块包装异常抛出代码,它将捕获异常那里,但如果异常传播到MFC代码它似乎吞下了。我想一个潜在的解决方法是自己使用try-catch块。 – AshleysBrain 2010-01-29 15:52:01

+0

我可以证实这个问题,它与Windows Vista 64位和Windows 7 64位上的OpenGL有关。寻找答案本人:) – ralphtheninja 2010-02-12 16:38:28

+0

这似乎类似于我的问题: http://stackoverflow.com/questions/2622200/exceptions-silently-caught-by-windows-how-to-handle-manually – 2010-04-12 13:25:32

回答

3

好吧,我发现了更多关于这方面的信息。在我的情况下,它是在调用我的WndProc并给予我执行控制之前安装KiUserCallbackExceptionHandler作为异常处理程序的Windows 7。这是通过ntdll!KiUserCallbackDispatcher完成的。我怀疑这是微软采取的一项安全措施,以防止黑客入侵SEH。

解决方案是用一个try/except帧包装你的wndproc(或者hookproc),这样你可以在Windows之前捕获异常。

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

我们已经联系的nVidia这个 问题,但他们说,这不是他们的错误 ,而是微软。请问 您可以告诉您如何找到 异常处理程序?你是否有 一些额外的信息,例如一些 来自微软的反馈?

我在WinDbg中使用了“!exchain”命令来获取这些信息。

+0

我们已经联系nVidia了解这个问题,但他们说这不是他们的错误,而是微软的。你能告诉你如何找到异常处理程序吗?并且您是否还有其他信息,例如一些来自微软的反馈? – Mikhail 2010-05-25 14:39:41

+0

SEH是最方便的答案,所以我会接受它。 – Mikhail 2012-03-15 16:51:45

0

首先,这两种行为都是正确的。解引用空指针是“未定义的行为”,而不是保证的访问冲突。首先,找出这是与异常抛出还是仅与访问内存位置零(尝试不同的异常)相关。

如果您将Visual Studio配置为停止一次访问冲突,它会中断吗?

在glMakeCurrent之前和之后调用VirtualQuery(NULL,...)并进行比较。也许nVidia OpenGL驱动程序VirtualAlloc页面为零(一个糟糕的主意,但不是不可能的或非法的)。

+0

相同的行为任何异常,包括用throw操作符手动引发。如果我将Visual Studio配置为停止一次性异常,则会中断。 – Mikhail 2010-02-16 09:07:50

+0

声音像一个向量异常处理程序被注册并吃掉异常。 http://msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx 打破第一次机会的例外,然后开始单步(确保您有选项“只是我的代码“禁用,以便您可以浏览其他库)。可能某个处理程序返回EXCEPTION_CONTINUE_EXECUTION而不是EXCEPTION_CONTINUE_SEARCH。 – 2010-02-17 21:59:52

+0

VirtualQuery(NULL,...)的比较结果,对于wglCreateContext()之前和之后的调用,结果相同。 – Mikhail 2010-02-18 06:49:33

1

而不是包裹的WndProc或钩住所有WndProcs,你可以使用向量异常处理:

http://msdn.microsoft.com/en-us/library/ms679274.aspx

+0

我做到了这一点,它为我工作。 – Brian 2011-12-06 22:56:53

+0

我收回。我们不得不恢复这一改变,因为它过于激进。有一些例外,我们想单独留下,并允许以正常方式处理,但我们无法将它们与我们想要崩溃的访问违规等相区分。 – Brian 2011-12-17 02:15:58

+0

我有一个用__try/__catch覆盖WndProc的所有用户界面的基类。处理程序然后在发布中调用崩溃记录器,在调试中继续,以便我们可以调试崩溃。 – 2011-12-18 19:58:31

0

我在查看类似问题时发现此问题。在64位Windows上运行32位应用程序时,我们的问题证明是无意中使用异常。

http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

有可从Microsoft修复,虽然部署它是有点挑战,如果你有多个目标平台:

http://support.microsoft.com/kb/976038

下面是关于这个问题的描述行为的文章:

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

在堆栈溢出此线程还介绍我遇到的问题: Exceptions silently caught by Windows, how to handle manually?

相关问题