这几天尝试创建一个dll玩,遇到一个困扰多时的bug,这个bug出现比较诡异。首先在vs中调用该dll没问题,在qt中调用却产生堆栈错误,错我大概是dbheap.c什么析构出问题了。搜索网络,首先排查运行时库是否正确,在编译生成dll和exe程序中都用的一样。然后搜到这篇文章,返回const引用则治好了这个问题,转载到这里以防万一,vector还是不会太会用~
下文转载自http://www.voidcn.com/blog/han6771306/article/p-1842348.html
今天在调试程序的时候遇到了这个问题。
先给出出问题的代码:
1 2 3 |
[.dll] vector<string> getPerList(){return _perList;} vector<string> getGrpList(){return _grpList;} |
调用该dll的代码:
1 2 3 4 5 6 |
[CContactDialog.cpp] list.requestPerList(p_contact->_id); list.requestGrpList(p_contact->_id); p_contact->_priv_list=list.getPerList(); p_contact->_grp_list=list.getGrpList(); |
其中_priv_list,_grp_list都是CContactDialog的vector<string>类型的成员变量。
出错提示:
在网上搜了下问题:
1 2 3 |
简单的讲把vector传入到dll中后,添加节点时,在dll中会进行一些内存分配,当vector析构时,由于申请和释放不是相同模块,这会导致vector不知道如何正确释放dll中分配的内存。 还有一个问题更严重一些,一般比较隐蔽。比如标准C++库中的大多数类都直接或间接使用静态数据。由于这些类通过模板实例生成的,每个映像包含一个给定的类的静态数据成员的副本。当你在dll中使用或更改静态数据成员时,(由于该静态成员的代码驻留在可执行映像中,比如EXE),会造成可执行模块中的静态数据成员不同步,这个动作可能会导致引发访问冲突或数据出现丢失和其它不可预知的结果。 |
解决:
把生成dll的代码修改如下
1 2 3 |
[.dll] const vector<string>& getPerList(){return _perList;} const vector<string>& getGrpList(){return _grpList;} |
我的理解是:
vector<string>作为返回值的时候,在dll中为临时对象分配内存,被调用dll的代码中超出该临时对象的作用域范围时,临时对象将被销毁,带正如上面说的一样,内存是在dll中分配的,却在调用dll的代码中释放,所以出现了错误。改成const vector<string>&后,dll中将不会产生临时对象,就不会出想这个问题。