捕获dll异常后的访问冲突 [英] Access violation after catching dll exception

查看:885
本文介绍了捕获dll异常后的访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在运行时动态地将模块加载为dll,因为它们不是提前知道的,只是它们符合类接口。我注意到的是,在我捕获dll抛出的异常(在主线程中的主程序中)之后,正确的析构函数被调用,并且模块被破坏,并且dll被卸载,但随后作为}在catch块的末尾当Visual Studio C ++调试器逐行走到时,我得到另一个例外,该程序崩溃了



0x68ad2377(msvcr90d.dll)中的第一次异常xxxxx.exe:0xC0000005:访问冲突读取位置0x02958f14。



如果我启用了异常,打破这个第二个异常显示位置为



msvcr90d.dll!__ DestructExceptionObject(EHExceptionRecord * pExcept = 0x0017ee4c,unsigned char fThrowNotAllowed = 0)行1803 + 0xf bytes



但它看起来像框架堆栈可能已损坏。我不知道为什么会抛出这个异常。



我的代码结构的简化版本如下:



程序非常简化的结构:

  //共享标题:
class Module
{
public:
virtual void Foo(void)= 0;
};


// dll:
class SomeSpecificModule:public Module
{
public:
virtual void Foo(void);
};

void SomeSpecificModule :: Foo(void)
{
throw 1;
}

externC__declspec(dllexport)模块* GetModule()
{
return new SomeSpecificModule;
}


//程序:
typedef ptrGetModule *(* GetModule)();

int main(void)
{
HANDLE hMod = LoadLibrary(SomeSpecificModule.dll);
ptrGetModule GetModule =(ptrGetModule)GetProcAddress(hMod,GetModule);
try
{
模块* d = GetModule();
d-> Foo();
}
catch(...)
{
cout<<< '!'<< ENDL;
}
return 0;
}


解决方案

要记住的是C运行时库的每个副本都有自己的状态。如果SomeSpecificModule.dll静态链接到C运行时库,则可能会发生这种问题。如果是这样,请尝试链接到C运行时库的DLL版本。您还必须确保SomeSpecificModule.dll的编译和链接与主模块完全相同。



您提到DLL被卸载并正确的析构函数被调用,像你的真实程序,比你发布的样品有更多的进展。如果您在您的try块中卸载了SomeSpecificModule.dll,那么您已经卸载了SomeSpecificModule :: Foo()的异常记录,我猜这是在m svcr90d.dll!__ DestructExceptionObject(EHExceptionRecord) * ...



但是,一般来说,跨DLL边界抛出异常是要求麻烦,如果你抛出非POD对象,你可能遇到不同的C运行时库分配的内存不同的堆,不同的编译器设置,STL版本...你得到的点。



更改你的代码,所以你有一天,你的团队中的某个人会改变编译器设置,或者第三方标题#define已更改,您的程序开始崩溃,您将很难追踪根本原因。



无论如何,没有看到真正的代码,我只是想猜猜可能会出错,希望有帮助。


I have to load modules as dlls dynamically at runtime as they are not known ahead of time, just that they conform to a class interface. What I noticed is that after I catch an exception thrown by the dll (in the main program in the main thread), the right destructors are called and the modules destroyed and dll's unloaded, but then as the } at the end of the catch block is reached by the Visual Studio C++ debugger when stepping line by line, I get another exception which crashes the program with

First-chance exception at 0x68ad2377 (msvcr90d.dll) in xxxxx.exe: 0xC0000005: Access violation reading location 0x02958f14.

If I enable breaking on exceptions, breaking on this second exception shows the location as

msvcr90d.dll!__DestructExceptionObject(EHExceptionRecord * pExcept=0x0017ee4c, unsigned char fThrowNotAllowed=0) Line 1803 + 0xf bytes

but it looks like the frame stack may be corrupt. I can't figure out why this exception is thrown.

A simplified version of my code structure is as follows:

A very simplified structure of the program:

//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;
}

解决方案

The thing to remember is that each copy of C runtime library has its own states. If SomeSpecificModule.dll is linking statically to the C runtime library, this kind of problem may happen. If that's the case, try linking with DLL version of of C runtime library. You also have to make sure SomeSpecificModule.dll is compiled and linked exactly the same way as your main module.

You mentioned DLL being unloaded and correct destructors were called, it sounded like your real program has a lot more going on than the sample you posted. If you unloaded SomeSpecificModule.dll in your try block, you've unloaded the exception record for SomeSpecificModule::Foo(), and I guess that's how you got the crash at msvcr90d.dll!__DestructExceptionObject(EHExceptionRecord * ...

However, in general throwing exception across DLL boundaries is asking for trouble. If you're throwing non POD object, you may run into issue with memory allocated by different C runtime library in different heap, different compiler setting, STL version...you get the point.

Change you code so you don't throw across DLL boundaries. One day someone from your team change the compiler setting or a third party header #define changed and your program start crashing you're going to have a very hard time tracing down the root cause.

Anyway, without seeing the real code, I'm just trying to guess what might go wrong. Hope it helps.

这篇关于捕获dll异常后的访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆