在DLL与EXE之间传递STL容器对象的问题总结

exemple1  
DLL:
insert(vector <string> *   pvstr)
{
vstr-> push_back( "111 ");
}
 
EXE:
{
vector <string>   vstr;
insert(&vstr);
}//ERROR1
 
解释:
EXE和DLL都有自己堆,所以在DLL里动态创建的东西,不能在调用DLL的进程里销毁,反之亦然。
上面的insert()在DLL堆里创建了string对象,而销毁这个对象的动作发生在EXE进程里,即vstr的析构。
 
exemple2
DLL:
foo1(vector <string>   vstr)
{
return;
}
 
vector <string> foo2()
{
vector <string>   vstring;
return   vstring;
}
 
EXE:
{
vector <string>   vstring;
foo1(vstring);//ERROR2
vstring=foo2();
 
}//ERROR3
 
错误的根本原因与exemple1相同,
ERROR2是因为vstring在EXE进程空间产生了一个vstring临时的副本vstr。这个副本引用了EXE空间分配的内存块,
但vstr却属于DLL里的foo1()的局部变量。当foo1()退出时,vstr析构。vstr在试图释放先前的内存块时,发生异常。
ERROR3和ERROR2类似,只不过这次临时变量实在DLL中产生而在EXE中销毁。
 
基于以上两点,DLL和EXE之间不能对有引用动态内存块成员变量的对象进行值传递,只能传指针或引用。
而且对传过来的对象不能进行可导致内存释放或重新分配的修改。
 
但下面这个例子,虽然是传指针并且是只读访问,但也有错误。
 
exemple3
 
DLL:
map <int,int> *   getData(){
map <int,int> *   pm=new   map <int,int> ();
pm-> insert(pair <string,string> (1,1));
return   pm;
}
 
EXE:
map <int,int> *   pm=getData();
map <int,int>   m   =*pm;//ERROR4
map <int,int> ::iterator   iter=pm-> begin();
while(iter   !=   pm-> end())
{
        cout   < <   (*iter).first   ;   //OK,output   "1 "
        iter++;//ERROR5
}
 
上面的错误在与STL的实现有关,我采用的是VC带的STL。里面的关联容器都使用一个叫_Tree的类,_Tree的空节点指针被定义一个
静态的成员函数:
xtree:424                 static   _Nodeptr   _Nil;
_Nil被当成关联容器的最后一个节点。但由于_Nil是静态的,所以一个进程空间只有一个_Nil节点。而DLL和EXE中的_Nil节点是不一样的。
当在EXE中遍历DLL创建的map对象时,会把DLL中的_Nil节点和EXE中的_Nil节点以确定是否到达最后一个节点。它们永远不会相等,也就找不到终止节点直到访问到非法地址空间而出错。
 
也就是说,动态连接库和调用动态连接库的进程之间,不能互访STL关联容器对象。同理不同进程之间也不能。
 
 
以上例子基于VC6.0

你可能感兴趣的:(vector,String,iterator,dll,insert,exe)