gpt4 book ai didi

c++ - 捕获dll异常后访问冲突

转载 作者:太空狗 更新时间:2023-10-29 20:01:27 24 4
gpt4 key购买 nike

我必须在运行时将模块作为 dll 动态加载,因为它们事先不知道,只是它们符合类接口(interface)。我注意到的是,在我捕获到 dll 抛出的异常(在主线程的主程序中)之后,调用了正确的析构函数并销毁了模块并卸载了 dll,但是随后作为 } 在 catch block 的末尾当逐行执行时,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 block 中卸载了 SomeSpecificModule.dll,那么您已经卸载了 SomeSpecificModule::Foo() 的异常记录,我想这就是您在 msvcr90d.dll!__DestructExceptionObject(EHExceptionRecord * .. .

但是,一般来说,跨 DLL 边界抛出异常是自找麻烦。如果您抛出非 POD 对象,您可能会遇到由不同堆、不同编译器设置、STL 版本中的不同 C 运行时库分配的内存问题……您明白了。

更改您的代码,以免超出 DLL 边界。有一天,您团队中的某个人更改了编译器设置或更改了第三方 header #define,您的程序开始崩溃,您将很难追查根本原因。

无论如何,在没有看到真正的代码的情况下,我只是想猜测可能出了什么问题。希望对您有所帮助。

关于c++ - 捕获dll异常后访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/967982/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com