我有一个用MSVS2005创建的基于MFC驱动的基于对话框的应用程序。这是我一步一步的问题。我的对话框和相应的点击处理程序上有一个按钮,代码如下:
int* i = 0;
*i = 3;
我正在运行程序的调试版本,当我点击按钮时,Visual Studio会捕获焦点并提醒“访问违规写入位置”异常,程序无法从错误中恢复,我所能做的就是停止调试。这是正确的行为。
现在我在OnInitDialog()
方法中添加一些OpenGL初始化代码:
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 :(得分:3)
好的,我发现了一些关于此的更多信息。在我的情况下,它是Windows 7,在调用我的WndProc并给我执行控制之前,将 KiUserCallbackExceptionHandler 安装为异常处理程序。这是由 ntdll!KiUserCallbackDispatcher 完成的。我怀疑这是微软为防止入侵SEH而采取的一项安全措施。
解决方案是使用try / except帧包装你的wndproc(或hookproc),这样你就可以在Windows之前捕获异常。
感谢Skywing在http://www.nynaeve.net/
我们已经联系过nVidia 问题,但他们说这不是他们的 错误,而是微软的。可以 你能告诉你如何定位 异常处理程序你有吗? 一些额外的信息,例如一些 微软的反馈意见?
我在WinDbg中使用了“!exchain”命令来获取此信息。
答案 1 :(得分:1)
您可以使用向量异常处理,而不是包装WndProc或挂钩所有WndProcs:
答案 2 :(得分:0)
首先,两种行为都是正确的。取消引用空指针是“未定义的行为”,而不是保证的访问冲突。
首先,找出这是与抛出异常有关还是仅与访问内存位置零有关(尝试不同的异常)。
如果将Visual Studio配置为在第一次机会访问违规时停止,它是否会中断?
在glMakeCurrent之前和之后调用VirtualQuery(NULL,...)并进行比较。也许nVidia OpenGL驱动VirtualAlloc页面零(一个坏主意,但不是不可能或非法)。
答案 3 :(得分:0)
我有类似的行为(nVidia的驱动程序安装了一个矢量异常处理程序,最终导致崩溃),请参阅: https://stackoverflow.com/questions/4876796/why-does-an-exception-handled-by-nvidias-opengl-driver-in-copydown-memmove-late
安装最新的nVidia驱动程序(2011年1月)时它就消失了。
答案 4 :(得分:0)
当我看到类似的问题时,我发现了这个问题。在64位Windows上运行32位应用程序时,我们的问题变成了异常的异常消耗。
Microsoft提供了一个修复程序,但如果您有多个目标平台,那么部署它会有些挑战:
http://support.microsoft.com/kb/976038
这是一篇关于描述行为的主题的文章:
堆栈溢出上的这个线程也描述了我遇到的问题: Exceptions silently caught by Windows, how to handle manually?