DLL导入导出STL类对象导致崩溃的问题
问题:
从某DLL中导出一个接口函数GetDirFileIdSet用于获取目录下所有文件的ID集合。函数声明如下,该函数传入一个std::set<UINT>类对象:
void GetDirFileIdSet(std::set<UINT>& rFileIdSet);
当在VS2008中编译的“数据文件编辑器”加载了在VC6中编译的DLL,并调用到GetDirFileIdSet时发生了崩溃。
原因:
在不同的DLL或EXE中通过指针或引用操作另一个DLL或EXE中的STL类对象时,会遇到严重的程序错误,包括数据错乱或丢失。
标准C++库的多数类直接或间接的使用了静态数据成员。由于这些类是通过模板创建实例的,所以每个可执行模块(DLL或EXE)包含了有关类静态数据成员的一份Copy。当STL类中的函数成员要求操作静态数据成员时,这个类操作的静态数据是此函数成员代码所在的执行模块中的数据。由于静态成员数据在可执行模块间不能保证同步,所以前面提到的操作会导致读取失败或数据混乱和丢失。
解决方法:
1. 在创建STL类对象的模块中导出读取函数。这些函数包装了STL类对象要求的功能。这样,STL类对象只在原模块中被读取。例如:假设Program.exe需要得到Library.dll内std::deque<UINT>类对象中的一个元素,Library.dll则要导出读取函数:
__declspec(dllexport) UINT GetItem(UINT unIndex);
Program.exe就可以调用此函数来得到队列的一个元素了。
2. 从一个模块中导出模板实例,在另一个模块中导入此实例。例如:Library.dll将std::map<int, MyClass>指针传给Program.exe中的一个函数,需要在Library.dll中导出MyClass类定义和std::map<int, MyClass>类定义。然后就可以类似这样调用:
std::map<int, MyClass> *pTheMap = GiveMeTheMap();
const MyClass* pszItem = GetTheMapItemX(pTheMap, x);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?