尝试从DLL加载的派生类实例访问基类向量成员时程序崩溃

时间:2012-04-20 10:48:53

标签: c++ visual-c++ inheritance dll

我遇到了一个奇怪的崩溃。我试图将我的应用程序的各种模块(基于MFC,在VS2005中开发)分离到DLL中。以下是我试图实现它的骨架代码:

在一个常见的Header文件中(比如base.h):

class Base {
    vector<message> messages;
    ...
    ...
};

在DLL源代码(比如class.h)的头文件中:

class Derived : public Base {
private:
    int hoo();
    ...
public:
    void foo();
    int goo();
    ...
};

extern "C" __declspec (dllexport) Derived* CreateDerived();

在class.cpp

 Derived* CreateDerived()
 {
    return new Derived;
 }

在主应用程序代码中的文件中:

#include "base.h"
#include "class.h"

typedef Derived* (*DerivedCreator)();
...
...

void LoadDll()
{
    //DLL Load Code...
    ...
    ...

    DerivedCreator creator = reinterpret_cast<DerivedCreator>(::GetProcAddress(dllHandle, "CreateDerived"));

    Derived* pDerived = creator();

    pDerived->messages.push_back(message("xyz"));//Crashes here...
}

问题是我尝试访问Base类的vector成员时代码崩溃了。这仅在发布模式下发生。它在调试模式下工作正常。我在发布模式下从Visual Studio执行它时得到的错误消息是:

“Microsoft Visual Studio C运行时库在Samsung SSD Magician.exe中检测到致命错误。

按Break调试程序或继续终止程序。“

但是当我直接执行发布二进制文件并将调试器附加到它时,我收到了访问冲突。此时,如果我在调试器中检查向量,它会在其中显示6位数的条目,它们都不可读。我能够在Derived指针中看到Base类的其余成员的正确值。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

将stl容器传递到DLL边界是危险的。 这里的原因是每个模块(主应用程序和DLL)都有自己的堆实例。如果在DLL的上下文中分配动态内存,则将指针传递给应用程序并在应用程序的上下文中释放该内存,从而导致堆损坏。

这正是你的例子中发生的事情。

Derived* pDerived = creator();
调用

CreateDerived

 Derived* CreateDerived()
 {
    return new Derived;
 }

new Derived在DLL堆中分配内存。

pDerived->messages.push_back(message("xyz"));

push_back内,为Base::messages分配了一个额外的内存,并且该分配在应用程序堆上完成。崩溃!

结论是您需要重新考虑DLL接口,以便仅在DLL内部对向量执行所有操作。