我遇到了第三方DLL的一个地狱般的问题,当它被卸载时会出现导致递归堆栈溢出崩溃的问题。我最终将这个模式放在堆栈上(使用windbg):
<Unloaded_ThirdParty.dll>+0xdd01
ntdll!ExecuteHandler2+0x26
ntdll!ExecuteHandler+0x24
ntdll!KiUserExceptionDispatcher+0xf
<Unloaded_ThirdParty.dll>+0xdd01
ntdll!ExecuteHandler2+0x26
ntdll!ExecuteHandler+0x24
ntdll!KiUserExceptionDispatcher+0xf
...
正如您猜测的那样,我没有ThirdParty.dll的源代码。
问:堆栈转储中的前缀“Unloaded_”是什么意思。我之前没有碰过这个。
答案 0 :(得分:8)
这意味着ThirdParty.dll
不再被引用,并且在崩溃发生时已从内存中删除。要找出实际的堆栈跟踪,您需要使用以下命令将.dll重新加载到内存中的原始位置:
.reload /f ThirdParty.dll=0xaaaaaaaa
当然,您需要将0xaaaaaaaa
替换为模块的原始基址。这可能有点难以确定模块是否已经卸载,但如果你有一个HMODULE
位于dll引用,那么HMODULE
的值就是基地址。最糟糕的情况是,您可以在代码中添加一个调试器跟踪语句,在您卸载它之前记录该组的HMODULE
。
答案 1 :(得分:1)
我之前遇到过这样的崩溃,正如JS指出的那样意味着dll在崩溃之前已被卸载。但是,将堆栈跟踪到该dll可能不一定会为您提供诊断问题所需的信息。
代码中的某些东西正在卸载库,因为它认为它已经完成了,但你仍然有一个指向它的指针(或它内部的一个函数)。我的猜测是回调,也许来自另一个线程。我建议在您的来源中搜索对FreeLibrary()
的任何调用,并在FreeLibrary
符号上添加断点。找出卸载库的位置,然后确保已重置引用该dll的所有数据。如果您有多个线程,请使用互斥锁。
一个可能对此非常有用的工具是优秀的Process Monitor,我认为它会显示你将加载和卸载事件,并为每个事件提供一个堆栈跟踪。