我遇到了奇怪的崩溃。我试图将我的应用程序(基于 MFC,在 VS2005 中开发)的各个模块分离到 DLL 中。以下是我如何实现它的骨架代码:
在通用头文件中(例如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();
在类.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...
}
问题是当我尝试访问基类的 vector 成员时代码崩溃了。这只发生在 Release模式下。它在 Debug模式下工作正常。当我在 Release模式下从 Visual Studio 执行它时收到的错误消息是:
“Microsoft Visual Studio C 运行时库在 Samsung SSD Magician.exe 中检测到 fatal error 。
按“Break”调试程序或按“Continue”终止程序。”
但是当我直接执行发布二进制文件并将调试器附加到它时,我收到了访问冲突。此时,如果我检查调试器中的 vector ,它会显示其中的 6 位条目,但没有一个是可读的。我可以在派生指针中看到基类其余成员的正确值。
任何帮助将不胜感激。
最佳答案
跨 DLL 边界传递 STL 容器是危险的。 原因是每个模块(主应用程序和 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 接口(interface),以便仅在 DLL 内部对 vector 执行所有操作。
关于c++ - 尝试从 DLL 加载的派生类实例访问基类 vector 成员时程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10244770/