在dll导出函数参数中传递map类型的参数,在函数内insert时出非法访问错
来源:互联网 发布:娥佩兰旗舰店真假 知乎 编辑:程序博客网 时间:2024/06/05 05:36
在多个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时出非法访问错
- string类型在参数传递中如何作为引用,如何在函数外修改函数内的string类型
- 在接口函数中传递数组参数
- &应用传递,在函数中改变参数
- 关于DLL中导出类、导出函数接口的参数
- dll导出中函数中使用CString类型的参数引发的ESP出错
- dll导出中函数中使用CString类型的参数引发的ESP出错
- C#中调用C++的dll的参数为指针类型的导出函数
- C#中调用C++的dll的参数为指针类型的导出函数
- 查看DLL中导出的函数及参数
- 一次python对dll的调用,传递string类型的参数作为调用函数的参数
- jquery.load()函数 在JSP中局部加载刷新页面时的参数传递及获取
- 在VB中实现向函数传递不定个数参数
- 在VB中实现向函数传递不定个数参数
- 在不同JFrame中如何利用函数来传递参数
- 二维数组作为参数在函数中传递
- JavaScript - 在函数中修改参数值、用对象实例作为参数传递修改参数
- 在js的function中动态传递字符串类型参数
- displaytag.properties
- 尚学堂学习笔记。。。
- Java Generics Programming
- 彻底了解指针数组,数组指针,以及函数指针,以及堆中的分配规则
- 用displaytag组件实现分页详解
- 在dll导出函数参数中传递map类型的参数,在函数内insert时出非法访问错
- POP 协议常见命令 解释
- c# 上传图片加文字水印及图片水印
- flex 去除Array中的重复数据 过滤重复值
- “成功不可复制”掌握增加外链的潜规则
- Jquery :not
- Ext 表格得到所有行,并得到相应的列值
- WPF实现不规则窗体(C#)
- 浑浑噩噩