我遇到了一个奇怪的崩溃。我试图将我的应用程序的各种模块(基于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类的其余成员的正确值。
非常感谢任何帮助。
答案 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内部对向量执行所有操作。