捕获dll异常后访问冲突
我必须在运行时动态地将模块加载为dll,因为它们不会提前知道,只是它们符合类接口。 我注意到,在我捕捉到dll抛出的异常(在主线程的主程序中)之后,正确的析构函数被调用并且模块被销毁并且dll被卸载,但是随后在catch块的末尾} Visual Studio C ++调试器在逐行执行时遇到了另一个异常,它使程序崩溃
xxxxx.exe中0x68ad2377(msvcr90d.dll)的第一次机会异常:0xC0000005:访问冲突读取位置0x02958f14。
如果我启用打破例外,打破第二个例外显示的位置为
msvcr90d.dll!__ DestructExceptionObject(EHExceptionRecord * pExcept = 0x0017ee4c,unsigned char fThrowNotAllowed = 0)行1803 + 0xf字节
但它看起来像帧堆栈可能已损坏。 我无法弄清楚为什么抛出这个异常。
我的代码结构的简化版本如下所示:
该计划的一个非常简化的结构:
//shared header:
class Module
{
public:
virtual void Foo(void) = 0;
};
//dll:
class SomeSpecificModule : public Module
{
public:
virtual void Foo(void);
};
void SomeSpecificModule::Foo(void)
{
throw 1;
}
extern "C" __declspec(dllexport) Module* GetModule()
{
return new SomeSpecificModule;
}
//program:
typedef ptrGetModule* (*GetModule)();
int main(void)
{
HANDLE hMod = LoadLibrary("SomeSpecificModule.dll");
ptrGetModule GetModule = (ptrGetModule)GetProcAddress(hMod, "GetModule");
try
{
Module *d = GetModule();
d->Foo();
}
catch (...)
{
cout << '!' << endl;
}
return 0;
}
需要记住的是C运行时库的每个副本都有自己的状态。 如果SomeSpecificModule.dll静态链接到C运行时库,则可能会发生此类问题。 如果是这种情况,请尝试链接C运行时库的DLL版本。 您还必须确保SomeSpecificModule.dll的编译和链接方式与主模块完全相同。
你提到DLL被卸载并调用了正确的析构函数,这听起来像你真正的程序比你发布的示例还要多。 如果你在你的try块中卸载了SomeSpecificModule.dll,你已经卸载了SomeSpecificModule :: Foo()的异常记录,并且我想你就是这样在svcr90d.dll!__DestructExceptionObject(EHExceptionRecord * ...
得到这个崩溃的svcr90d.dll!__DestructExceptionObject(EHExceptionRecord * ...
但是,通常在DLL边界上引发异常会造成麻烦。 如果抛出非POD对象,则可能会遇到由不同堆中的不同C运行时库分配的内存,不同的编译器设置,STL版本等问题......您明白了。
改变你的代码,所以你不会抛出DLL边界。 有一天,来自团队的某人改变了编译器设置或第三方头文件#define改变了,你的程序开始崩溃,你将很难追查根本原因。
无论如何,没有看到真实的代码,我只是想猜猜可能会出错。 希望能帮助到你。
大部分需要在DLL引发异常时调用的堆栈展开代码位于DLL中。 如果卸载DLL,该代码如何被调用?
不要在动态链接的模块边界上抛出异常。
你是否在实际代码中通过价值来引发异常? 在这种情况下,在catch块的末尾复制的异常对象的析构函数中可能会有异常。
链接地址: http://www.djcxy.com/p/95497.html