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

原创 2007年09月13日 10:05:00
在多个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();  
        }   
 

同一个dll被多个进程使用的数据共享(Data_seg)

同一个dll被多个进程使用的时候,在大多数情况下,各个进程使用dll和独自使用dll效果是相同的。 因为对于dll中的局部变量是写入到进程的堆栈中的,全局变量也被操作系统为每个线程copy一份...

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

exemple1   DLL: insert(vector *   pvstr) { vstr-> push_back( "111 "); }   EXE: { ...

MFC中获取各个窗体之间的句柄或者指针对象的方法

MFC在很多的对话框操作中,我们经常要用到在一个对话框中调用另一个对话框的函数或变量.可以用如下方法来解决.    HWND hWnd=::FindWindow(NULL,_T("Sphere"))...
  • ghevinn
  • ghevinn
  • 2015年07月15日 14:49
  • 2102

MFC中获取各个窗体之间的句柄或者指针对象的方法 .

MFC在很多的对话框操作中,我们经常要用到在一个对话框中调用另一个对话框的函数或变量.可以用如下方法来解决.    HWND hWnd=::FindWindow(NULL,_T("Sphere"))...

Activity传递一个或者多个对象

Activity传递一个或者多个对象 博客分类: android_activity   Activity之间传递对象,或者通过Bundle传递对象的两种方式。 1:Seria...

Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]

      在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSerializable(Key,Object);也可以考虑采用Bundle.putParcela...
  • cjjky
  • cjjky
  • 2011年05月23日 23:08
  • 56032

Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable] .

在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSerializable(Key,Object);也可以考虑采用Bundle.putParcelable(Ke...

从内存中加载映像(EXE/DLL)到本地或者远程进程执行

被加载的映像EXE,固定基址(/FIXED:NO)即必须有重定位表, 否则无法处理重定位. 在vs的linker->advanced 中设置 fixed base address。 从其他博主中摘...

从内存中加载映像(EXE/DLL)到本地或者远程进程执行

被加载的映像EXE,固定基址(/FIXED:NO)即必须有重定位表, 否则无法处理重定位. 在vs的linker->advanced 中设置 fixed base address。 从其他博主中摘...
  • ooyyee
  • ooyyee
  • 2016年07月06日 20:28
  • 956

获取EXE或者DLL的版本信息

2017年第一篇博客,分享一个获取exe或者dll版本信息的成熟类: 头文件如下: // -----------------------------------------------------...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多个DLL(exe)之间通过指针或者引用传递STL对象
举报原因:
原因补充:

(最多只允许输入30个字)