关于Cross-Dll问题(在不同的模块之间申请和释放内存)

来源:互联网 发布:屏蔽软件弹出广告 编辑:程序博客网 时间:2024/06/09 23:29

           所谓Cross_Dll问题,就是在一个dll中申请了一段内存空间,在外部程序调用完该dll提供的功能后,为了不造成内存泄露,要释放掉在dll内部申请的空间。但是这种操作会引起程序崩溃。如下面的示例程序所示:

 

#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)#endifDLL_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的时候,会自动释放内存。


 

原创粉丝点击