您的位置:首页 > 其它

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

2010-09-07 15:13 696 查看
在多个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)
= 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();
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐