多个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();  
        }   
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

STL源码剖析笔记1

STL六大组件 容器:各种数据结构包括vector,list,set,map,STL容器class template。 常用的算法 迭代器:扮演算法和容器的,是为谓的泛型指针。 仿函数functors...

生成lib和使用lib方法详解

由于曾经在调用lib文件配置环境没有成功,特地研究了下lib文件,写一篇文章来简单叙述lib文件的编写使用。   生成lib 首先环境是VS2010,其它环境大同小异,请自己尝试。新建一个Win...

STL源码笔记(18)—平衡二叉树AVL(C++封装+模板)

平衡二叉树AVL 简介,C++ 封装与模板的实现

STL系列之五 priority_queue 优先级队列

priority_queue 优先级队列是一个拥有权值概念的单向队列queue,在这个队列中,所有元素是按优先级排列的(也可以认为queue是个按进入队列的先后做为优先级的优先级队列——先进入队列的元...

windows类书的学习心得

windows类书的学习心得 这篇文章应该是凑的,不够很长,还是值得读的,转发来。下满是原网址: http://www.blogjava.net/sound/archive/2008/08/2...

标准模板库STL(Standard Template Library)

标准模板库STL(Standard Template Library)

简单的程序诠释C++ STL算法系列之十五:swap

相信大家看到swap这个词都一定不会感到陌生,甚至会有这样想法:这不就是简单的元素交换嘛。的确,swap交换函数是仅次于Hello word这样老得不能老的词,然而,泛型算法东风,这个小小的玩意儿却在...

那些C++牛人的博客

那些C++牛人的博客 这篇文章来自转载,转载的网址找不到了, 如果有人知道,可以在下面评论, 非常感谢,更感谢原作者。 现整理收集C...

一个优秀程序员的成长之路

转载自: 酷壳 网址:   http://coolshell.cn/articles/4990.html 月光博客6月12日发表了《写给新手程序员的一封信》,翻译自《An open l...

C++著名程序库的比较和学习经验(STL.Boost.GUI.XML.网络等等)

1、C++各大有名库的介绍——C++标准库2、C++各大有名库的介绍——准标准库Boost3、C++各大有名库的介绍——GUI4、C++各大有名库的介绍——网络通信5、C++各大有名库的介绍——XML...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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