在dll导出函数参数中传递map类型的参数,在函数内insert时出非法访问错


        在多个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();
      }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值