在多个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导出函数参数中传递map类型的参数,在函数内insert时出非法访问错
最新推荐文章于 2021-03-08 15:55:42 发布