关于Cross-Dll问题(在不同的模块之间申请和释放内存)
2013-05-25 21:10
519 查看
所谓Cross_Dll问题,就是在一个dll中申请了一段内存空间,在外部程序调用完该dll提供的功能后,为了不造成内存泄露,要释放掉在dll内部申请的空间。但是这种操作会引起程序崩溃。如下面的示例程序所示:
以上为dll的源码,起名为dll_new.dll
下面是调用该dll的程序:
如上述程序所示:指针p在dll的函数new_test中申请了空间,但是在外面程序delete的时候,会引起程序崩溃。
原因分析:
模块之间分配和释放内存有一些不安全因素,因为不同模块(特别是不同语言开发的模块)可能使用了不同的内存管理机制,这种情况是不是跨模块释放的,所以VC的Debug版中对内存释放做了检查,如果发现不是本模块分配的就会报错。
造成失败的原因是分配和释放内存不是由相同的堆管理程序完成的,例如动态链接库中的堆在默认情况下是由msvcrt.dll中的堆管理程序管理的 (以动态链接的方式),而exe程序的堆在默认情况下是由程序自己的代码管理(以静态链接的方式),由于它们的堆管理程序不同,当动态链接库分配的内存在 exe程序中释放时就会出错,因为exe程序所在的堆并没有分配这块内存,而你却要求它释放这块内存。
解决方法(三种解决办法):
1、将程序中所有的模块都链接到C/C++运行期库Multithreaded DLL,修改后所有分配和释放堆上内存的操作都由同一个堆管理程序管理,这样便解决了问题。
2、 在DLL中增加一个导出函数来释放内存。谁负责分配,谁就必须负责释放!
3、使用智能指针,如std::shared_ptr。这样不用自己释放内存,智能指针在发现引用计数为1的时候,会自动释放内存。
#ifndef DLL_NEW_H_ #define DLL_NEW_H_ #ifndef _DLL_NEW_DLL_ #define DLL_NEW_API __declspec(dllimport) #else #define DLL_NEW_API __declspec(dllexport) #endif DLL_NEW_API void new_test(int * &p); #endif
#include "dll_new.h" void new_test(int * &p) { p=new int; *p=12; }
以上为dll的源码,起名为dll_new.dll
下面是调用该dll的程序:
#include "dll_new.h" #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include <stdio.h> #pragma comment(lib,"dll_new.lib") //在dll中new出来的空间要在dll内部delete掉,如果在调用dll的外部程序中释放的话,会崩溃 void main() { /***********用于检测内存泄露**************/ //此代码检测不出dll里面的内存泄露!!! int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); tmpFlag |= _CRTDBG_LEAK_CHECK_DF; _CrtSetDbgFlag( tmpFlag ); /*************用于检测内存泄露********************/ int *p=NULL; new_test(p); printf("%d\n",*p); delete p; }
如上述程序所示:指针p在dll的函数new_test中申请了空间,但是在外面程序delete的时候,会引起程序崩溃。
原因分析:
模块之间分配和释放内存有一些不安全因素,因为不同模块(特别是不同语言开发的模块)可能使用了不同的内存管理机制,这种情况是不是跨模块释放的,所以VC的Debug版中对内存释放做了检查,如果发现不是本模块分配的就会报错。
造成失败的原因是分配和释放内存不是由相同的堆管理程序完成的,例如动态链接库中的堆在默认情况下是由msvcrt.dll中的堆管理程序管理的 (以动态链接的方式),而exe程序的堆在默认情况下是由程序自己的代码管理(以静态链接的方式),由于它们的堆管理程序不同,当动态链接库分配的内存在 exe程序中释放时就会出错,因为exe程序所在的堆并没有分配这块内存,而你却要求它释放这块内存。
解决方法(三种解决办法):
1、将程序中所有的模块都链接到C/C++运行期库Multithreaded DLL,修改后所有分配和释放堆上内存的操作都由同一个堆管理程序管理,这样便解决了问题。
2、 在DLL中增加一个导出函数来释放内存。谁负责分配,谁就必须负责释放!
3、使用智能指针,如std::shared_ptr。这样不用自己释放内存,智能指针在发现引用计数为1的时候,会自动释放内存。
相关文章推荐
- 关于在dll中申请内存,外部释放的问题
- 关于在dll中申请内存,外部释放的问题
- 关于在dll中申请内存,外部释放的问题
- 关于在dll中申请内存,外部释放的问题
- 不同运行时库/MT、/MD等编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- 跨module(exe、dll)间传递c++对象发生申请/释放内存违例的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- dll的内存申请和释放问题--Debug程序正常而Release程序崩溃
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- 【C/C++开发】C语言 DLL(动态链接库)中申请动态内存释放的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- 关于库函数里申请的内存空间在库函数外释放的问题的一些总结