随笔-1  评论-6  文章-0  trackbacks-0
这是在项目中碰到的。
下面是代码:
//de.cpp
#include <string>
#include 
<iostream>
using namespace std;
extern "C" void getString(string &
str);

int main(int argc,char **
argv)
{
    
string
 str;
    getString(str);
    cout 
<<
 str;
    
return 0
;
}

//dll.cpp
#include <string>
#include 
<iostream>
using namespace std;
extern "C" void getString(string &
str)
{
    
int
 i;
    
str += "string modified.mybe cause a exception.";
}

将dll.cpp连接成dll形式,运行de.exe有时候很正常,但有时候会发现有异常出现,异常是delete释放了一个非法的指针。这取决于连接的运行库是动态的还是静态的,他会在静态连接时出问题。
产生这个问题的原因是因为std::string类的内存分配器分配了内存,而在de.cpp里释放,两个模块分别有自己的运行堆,分配和释放没有在同一个堆里进行。
原因很简单,但是有时后就会忽略,尤其在模块很多和频繁使用stl容器的时候,当从别人那里得到一个模块接口时,如果有一个需要stl容器引用的接口时就要注意运行库的问题。
posted on 2005-11-24 10:24 psysun 阅读(3270) 评论(6)  编辑 收藏 引用

评论:
# re: 在跨模块调用中传递stl容器的问题。 2005-11-24 13:41 | 小明
link 的时候使用C++ Multi Thread Dll 库,就应该没问题  回复  更多评论
  
# re: 在跨模块调用中传递stl容器的问题。 2005-11-24 17:39 | psysun
和多线程库没关系,是连接方式的问题。
总的原则是:在跨模块的接口里如果有用非常量stl容器引用作为参数的函数,那么就要保证这两个模块都用动态连接运行库方式连接的。用指针传递参数时分配和释放不再同一模块也有同样的问题。  回复  更多评论
  
# re: 在跨模块调用中传递stl容器的问题。 2005-11-28 13:52 | hotjock
是不是用动态方式链接就能保证调用模块和被调用模块公用一个堆?还有就是STL如何释放或者讲何时释放由被调用模块重新new出来的空间(就象上面例子中的那样),采用动态链接就一定可以避免吗?  回复  更多评论
  
# re: 在跨模块调用中传递stl容器的问题。 2005-11-28 19:23 | psysun
和动态链接没关系,重要的是共享运行时库。
因为stl容器都是以头文件形式定义的,所以每个模块编译后都至少有一份stl代码,在上面的例子里operator+=就是在dll.obj模块里,而~string()代码在de.obj,他们都使用了allocator<>,这个模版最后会用malloc和free管理内存,这时如果有一个模块静态链接了运行库,那么堆就不是唯一的,就会出异常了。
stl容器在分配内存时会根据算法用malloc分配一个比需要更大的内存,free掉原来的内存,用new(p) value_type(x)构造新对象,调用的是拷贝构造函数,用p->~value_type()析构对象。  回复  更多评论
  
# re: 在跨模块调用中传递stl容器的问题。 2005-11-29 17:21 | hotjock
如同你最初给出的那个例子,怎样做就可以保证不出异常。

一个新手,希望讲的详细些。  回复  更多评论
  
# re: 在跨模块调用中传递stl容器的问题。 2005-12-11 23:30 | psysun
再连接时用动态方式链接运行库就能避免了。vc里就是/MD  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理