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

C++中内存泄露检测

2015-10-30 14:17 429 查看
内存泄露的关键就是记录分配的内存和释放内存的操作,看看能不能匹配。跟踪每一块内存的声明周期,例如:每当申请一块内存后,把指向它的指针加入到List中,当释放时,再把对应的指针从List中删除,到程序最后检查List就可以知道有没有内存泄露了。Window平台下的Visual Studio调试器和C运行时(CRT)就是用这个原理来检测内存泄露。

在VS中使用时,需加上

#define _CRTDBG_MAP_ALLOC

#include <crtdbg.h>

通过包括 crtdbg.h,将 mallocfree 函数映射到其“Debug”版本 _malloc_dbg_free_dbg,这些函数将跟踪内存分配和释放。此映射只在调试版本(在其中定义了 _DEBUG)中发生。发布版本使用普通的 malloc 和 free 函数。

#define 语句将 CRT 堆函数的基版本映射到对应的“Debug”版本。并非绝对需要该语句,但如果没有该语句,内存泄漏转储包含的有用信息将较少。
_CrtDumpMemoryLeaks();

函数将显示当前内存泄露,也就是说程序运行到此行代码时的内存泄露,所有未销毁的对象都会报出内存泄露,因此要让这个函数尽量放到最后。

#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
#include<iostream>
using namespace std;
int main()
{
char*str1= (char*)malloc(100);
char*str2 = (char*)malloc(50);
deletestr1;
//输出内存泄露信息
_CrtDumpMemoryLeaks();
return0;
}

由上述代码可知,申请了两块内存,仅释放了一块内存。

运行调试会在输出窗口中输出如下信息:

Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(18): {144} normal block at 0x007B9D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dump complete.

如果没有#define _CRTDBG_MAP_ALLOC就会输出如下信息:
Detected memory leaks!
Dumping objects ->
{144} normal block at 0x00389D70, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.

未定义 _CRTDBG_MAP_ALLOC 时,所显示的会是:

内存分配编号(在大括号内)。
块类型(普通、客户端或 CRT)。
十六进制形式的内存位置。
以字节为单位的块大小。
前 16 字节的内容(亦为十六进制)。

定义了 _CRTDBG_MAP_ALLOC 时,还会显示在其中分配泄漏的内存的文件。文件名后括号中的数字(本示例中为
18)是该文件内的行号。

当我们使用new分配内存时,即使加上宏定义#define _CRTDBG_MAP_ALLOC,也不会检测到程序中内存申请的位置(行号)。因为刚刚包含头文件和加宏定义(_DEBUG)只重载了malloc函数,并没有重载new操作符,所以要自己定义重载new操作符才能检测到泄露内存的申请位置。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];

_CrtDumpMemoryLeaks();
return 0;
}

这样用new分配内存之后,运行调试程序,这样就会输出带分配内存而泄露的申请位置会,输出如下:

Detected memory leaks!
Dumping objects ->
d:\workspaces\vs_2013\effective_c++_projects\检测内存泄露\memoryleaks1.cpp(22) : {145} normal block at0x00619DE0, 50 bytes long.
Data: < > CD CD CD CD CD CD CD CD CDCD CD CD CD CD CD CD
Object dumpcomplete.

_CrtSetDbgFlag

如果程序总是在同一位置退出,调用 _CrtDumpMemoryLeaks 将非常容易。如果程序从多个位置退出,则无需在每个可能退出的位置放置对 _CrtDumpMemoryLeaks 的调用,而可以在程序开始处包含以下调用:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

该语句在程序退出时自动调用 _CrtDumpMemoryLeaks。必须同时设置 _CRTDBG_ALLOC_MEM_DF 和_CRTDBG_ALLOC_MEM_DF 两个位域,如上所示。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG //重载new
//FILE和LINE前后是两个——
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
_CrtSetDbgFlag(_CRTDBG_MALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF)
char *str1 = NULL;
char *str2 = NULL;
str1=(char*)malloc(100);
str2=new char[50];

return 0;
}

这样就不需要显示调用_CrtDumpMemoryLeaks()函数,_CrtSetDbgFlag在文件结束时,会自动调用用_CrtDumpMemoryLeaks()。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: