多个DLL(exe)之间通过指针或者引用传递STL对象

在多个DLL(exe)之间通过指针或者引用传递STL对象时会发现操作失败现象。MSDN上给出了完整的解决方法。在开发应用程序的过程中需要认真对待。  
   
  现象:  
   
  在不同的DLL或EXE中通过指针或引用操作另一个DLL或EXE中的STL对象时,会遇到严重的程序错误,包括数据错乱或丢失。  
   
  原因:  
   
  标准C++库的多数类直接或间接的使用了静态数据成员。由于这些类是通过模板创建实例的,所以每个可执行程序(一般是有DLL或EXE扩展名的)包含了有关类静态数据成员的一份Copy。当STL类中的方法要求操作静态数据成员时,这个类操作的静态数据是此方法代码所在的执行程序中的数据。由于静态成员数据在可执行程序中不能保证同步,所以前面提到的操作会导致读取失败或数据混乱和丢失。  
   
  解决方法:  
   
  1. 在创建STL对象的可执行程序中输出读取的方法(函数)。这些函数包装STL对象要求的功能。这样,STL对象只能在单个可执行程序中被直接读取。例如:假设MyProgram.EXX需要得到MyLibrary.DLL   内deque<MyClass   >中的下一个元素,MyLibrary.DLL则要输出读取方法:“MyClass*   DequeNextItem   (/*...*/);”。MyProgram.EXE就可以执行此方法来得到队列的下一个元素了。  
  2. 从一个可执行程序中输出模板实例,在另一个可执行程序中引入此实例。例如:MyLibrary.DLL将vector<MyClass>指针回传给MyProgram.EXE中的一个函数,需要在MyLibrary.DLL中输出MyClass类和vector<MyClass>。在MyProgram.EXE中引入它们后。就可以得到MyLibrary.DLL中静态数据成员的一份Copy了。  
   
  例子程序:  
  //---------------------------------------------------------  
        //   AVEXE.CPP  
        //   Compile   options   needed:   /GX  
        #pragma   warning   (disable   :   4786)  
        #include   <map>  
        #include   <string>  
        #include   <stdio.h>  
        __declspec(dllimport)       std::map<int,std::string>*   GiveMeAMap(int   n);  
        __declspec(dllimport)       void   ShowMeTheMap(std::map<int,std::string>   *amap);  
        __declspec(dllexport)       const   char*   MapItemX   (std::map<int,std::string>   *m,   int   x);  
        int   main   ()   {  
              //   Create   the   map   in   the   DLL  
              int   x   =   6;  
              std::map<int,std::string>   *p   =   GiveMeAMap(x);  
   
              //   Display   the   contents   of   the   map   from   the   DLL  
              printf("Showing   contents   from   the   DLL/n");  
              ShowMeTheMap(p);  
   
              //   Display   the   contents   of   the   map   from   the   EXE  
              //   using   the   accessor   function   from   the   DLL   so   we  
              //   aren't   directly   accessing   the   map  
              printf("Showing   contents   from   the   EXE   using   accessor/n");  
              int   i   =   x;  
              while   (i--)   {  
                    printf("%d   =   %s/n",i,MapItemX(p,i));  
              }  
   
              //   Access   Violation   when   accessing   the   map   that  
              //   was   created   in   the   DLL   from   the   EXE  
              printf("Showing   contents   from   the   EXE   directly/n");  
              while   (x--)   {  
                    printf("%d   =   %s/n",x,(*p)[x].c_str());  
              }  
   
              return   0;  
        }  
   
        //---------------------------------------------------------  
        //   AVDLL.CPP  
        //   Compile   options   needed   /GX  
        #pragma   warning   (disable   :   4786)  
        #include   <map>  
        #include   <string>  
        #include   <stdlib.h>  
   
        //   Create   the   map   here   in   the   DLL  
        __declspec(dllexport)       std::map<int,std::string>*   GiveMeAMap(int   n)    
  {  
              std::map<int,std::string>   *m   =   new   std::map<int,std::string>;  
              while(n--)   {  
                    char   b[33];  
                    itoa(n,b,2);  
                    (*m)[n]   =   std::string(b);  
              }  
              return   m;  
        }  
   
        //   We   can   access   the   map   without   error   from   the   executable  
        //   image   where   the   map   was   created  
        __declspec(dllexport)     void   ShowMeTheMap(std::map<int,std::string>   *p)    
  {  
              int   x   =   p->size();  
              while   (x--)   {  
                    printf("%d   =   %s/n",x,(*p)[x].c_str());  
              }  
        }  
   
        //   An   accessor   method   to   return   the   associated   C   string  
        //   for   key   x  
        __declspec(dllexport)     const   char*   MapItemX   (std::map<int,std::string>   *m,   int   x)    
  {  
              return   (*m)[x].c_str();  
        }   
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值