为什么AddVectoredExceptionHandler会导致我的DLL崩溃?

3
我尝试在我的Win32 DLL中添加向量异常处理,但调用AddVectoredExceptionHandler从未返回。我只得到无用的<app name>.exe已停止工作对话框。然而,如果我使用Visual C++调试器调试dll,则它可以正常工作,并且处理程序函数会在适当的时间调用,一切都很好。
具体来说,我是在我的DLL初始化时添加处理程序,如下所示:
OutputDebugString("before adding\n");
AddVectoredExceptionHandler( 1, VectoredExcepHandler );
OutputDebugString("after adding\n");

当未经过调试器运行时,DebugView 显示的是 "添加前" 而不是 "添加后"。

这个处理程序看起来像下面这样:

static LONG CALLBACK VectoredExcepHandler( PEXCEPTION_POINTERS exInfo )
{
    OutputDebugString("reached handler\n");
    return EXCEPTION_CONTINUE_SEARCH;
}

噢,如果有关系的话,我正在运行Vista Home 64。

事件查看器显示错误是kernel32.dll中的访问冲突。


进一步的发现几乎解决了问题:我发现,如果我在句柄中注释掉OutputDebugString调用,则错误会消失。所以我猜测有一些异常与OutputDebugString不兼容。显然它不是一些常见的异常代码,比如访问冲突和非法指令,因为如果我在调用OutputDebugString之前检查这些异常代码,一切都很好。


你的dll在异常发生时可能已经被卸载了,这种情况是否有可能出现?请注意,DebugView并非100%可靠 - OutputDebugString调用可能会丢失。 - 500 - Internal Server Error
@500-服务器内部错误:.exe从未尝试卸载.dll,即使没有异常,使用AddVectoredExceptionHandler仍会出现问题。 - JWWalker
我知道它在Vista x64上可以正常运行,我已经使用过了。至少给我们展示一下调用堆栈。使用“工具+附加到进程”来附加调试器。假设是环境问题。 - Hans Passant
@HansPassant,如果您的意思是在“已停止工作”对话框出现后附加到进程,则调用堆栈窗口中永远不会出现任何内容。如果我单击对话框中的调试按钮,则唯一提供的调试器是Visual Studio 2010,而我没有许可证,而不是我使用的Visual Studio 2010 Express。但是,我将编辑问题以显示我发现的更多信息。 - JWWalker
1个回答

6
OutputDebugString每次调用时都会引发异常。因此,您的异常处理程序通过调用它导致无限递归,并导致堆栈溢出。有关更多详细信息,请参见此处
在内部,调试字符串被处理为异常。OutputDebugString使用DBG_PRINTEXCEPTION_C(定义为0x40010006)和字符串地址以及大小作为异常参数调用RaiseException。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接