其他分享
首页 > 其他分享> > c – 捕获dll异常后访问冲突

c – 捕获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版本的C运行时库的DLL版本.您还必须确保SomeSpecificModule.dll的编译和链接方式与主模块完全相同.

你提到DLL被卸载并且调用了正确的析构函数,听起来你的真实程序比你发布的样本还要多得多.如果您在try块中卸载了SomeSpecificModule.dll,那么您已经卸载了SomeSpecificModule :: Foo()的异常记录,我想这就是你在msvcr90d.dll崩溃的原因!__ DestructExceptionObject(EHExceptionRecord * …

但是,通常在DLL边界上抛出异常会造成麻烦.如果您正在抛出非POD对象,则可能会遇到由不同堆,不同编译器设置,STL版本中的不同C运行时库分配的内存问题…您明白了.

更改代码,这样就不会抛出DLL边界.有一天,你团队中的某个人改变了编译器设置或第三方标题#define已经改变,你的程序开始崩溃,你将很难找到根本原因.

无论如何,没有看到真正的代码,我只是想猜测可能会出现什么问题.希望能帮助到你.

标签:access-violation,c,exception,virtual,dll
来源: https://codeday.me/bug/20190724/1520104.html