捕获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

上一篇: Access violation after catching dll exception

下一篇: C++ Game Library/ Engine like LWJGL in Java