您的位置:首页 > 编程语言 > C语言/C++

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

2013-05-25 21:10 519 查看
           所谓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)
#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的时候,会自动释放内存。

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