一、 在 MFC 中检测内存泄漏
假如是用MFC的程序的话,很简单。默认的就有内存泄露检测的功能。
我们用VS2005生成了一个MFC的对话框的程序,发现他可以自动的检测内存泄露。不用我们做任何特殊的操作。 仔细观察,发现在每个CPP文件中,都有下面的代码:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
DEBUG_NEW 这个宏定义在afx.h文件中,就是它帮助我们定位内存泄漏。
在含有以上代码的cpp文件中分配内存后假如没有删除,那么停止程序的时候,VisualStudio的Output窗口就会显示如下的信息了:
Detected memory leaks!
Dumping objects ->
d:\code\mfctest\mfctest.cpp(80) : {157} normal block at 0x003AF170, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.
在Output窗口双击粗体字那一行,那么IDE就会打开该文件,定位到该行,很容易看出是哪出现了内存泄露。
二、检测纯C++的程序内存泄露
我试了下用VisualStudio建立的Win32 Console Application和Win32 Project项目,结果都不能检测出内存泄露
下面一步一步来把程序的内存泄露检测的机制建立起来。
首先,我们需要知道C运行库的Debug版本提供了许多检测功能,使得我们更容易的Debug程序。在MSDN中有专门的章节讲这个,叫做Debug Routines,建议大家先看看里面的内容吧。
我们会用到里面很重要的几个函数。其中最重要的是 _CrtDumpMemoryLeaks();自己看MSDN里的帮助吧。使用这个函数,需要包含头文件crtdbg.h
该函数只在Debug版本才有用,当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在"Output(输出)"窗口中显示内存泄漏信息。写段代码试验一下吧,如下:
检测内存泄露版本一:
#include "stdafx.h"
#include <crtdbg.h>
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int();
_CrtDumpMemoryLeaks();
return 0;
}
运行后,在Output(输出)窗口,显示了如下的信息:
Detected memory leaks!
Dumping objects ->
{112} normal block at 0x003AA770, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.
但是这个只是告诉我们程序有内存泄露,到底在哪泄露了一眼看不出来啊。
看我们的检测内存泄露版本二:
#include "stdafx.h"
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int();
_CrtDumpMemoryLeaks();
return 0;
}
包含头文件
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h>
函数原型 int __cdecl _CrtSetDbgFlag( __in int _NewFlag );
参数为_crtDbgFlag的新状态,返回值为_crtDbgFlag上一个状态
通过检测或者修改_crtDbgFlag标识的状态去控制堆的分配,并只能用于debug下
包含在crtdbg.h中
_crtDbgFlag的取值可以为:
#define _CRTDBG_ALLOC_MEM_DF 0x01 /* Turn on debug allocation */ #define _CRTDBG_DELAY_FREE_MEM_DF 0x02 /* Don't actually free memory */ #define _CRTDBG_CHECK_ALWAYS_DF 0x04 /* Check heap every alloc/dealloc */ #define _CRTDBG_RESERVED_DF 0x08 /* Reserved - do not use */ #define _CRTDBG_CHECK_CRT_DF 0x10 /* Leak check/diff CRT blocks */ #define _CRTDBG_LEAK_CHECK_DF 0x20 /* Leak check at program exit */
默认情况下,这几个状态都是关闭的
使用_CrtDumpMemoryLeaks();打印检测信息
详见http://msdn.microsoft.com/en-us/library/5at7yxcs(v=vs.71).aspx
1.addmemory leak detect macroin a common header file(确保项目中的其它源文件都需要include到这个头文件):宏抽到一个公共头文件是为了使内存泄露检测及定位覆盖到整个项目中,避免泄露无法定位.需要开启的宏如下:
- //malloc memory leak detect
- #define_CRTDBG_MAP_ALLOC
- #include<stdlib.h>
- #include<crtdbg.h>
- //new memory leak detect
- #definenew new(_NORMAL_BLOCK, __FILE__, __LINE__)
//malloc memory leak detect
#define_CRTDBG_MAP_ALLOC
#include<stdlib.h>
#include<crtdbg.h>
//new memory leak detect
#definenew new(_NORMAL_BLOCK, __FILE__, __LINE__)
2.Add memory leak detect code in the start of project,code如下:
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF|_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF|_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
3.Example:
- #include "stdafx.h"
- #ifdef _DEBUG
- //malloc memory leak detect
- #define _CRTDBG_MAP_ALLOC
- #include <stdlib.h>
- #include <crtdbg.h>
- //new memory leak detect
- #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
- inline void EnableMemLeakCheck()
- {
- _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
- //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
- //_CrtDumpMemoryLeaks();
- }
- #endif
- int _tmain(int argc, _TCHAR* argv[])
- {
- //_CrtSetBreakAlloc(91);
- int* arrValue= new int(10);
- int* pValueVec = (int*)malloc(4);
- #ifdef _DEBUG
- EnableMemLeakCheck();
- #endif
- return 0;
- }
- Output浮动面板的检测到的内存泄露的信息如下:(红色代表泄露的代码位置,通过双击该行可以直接定位到源码处)
- Detected memory leaks!
- Dumping objects ->
- e:\project\memory_lean_dection_demo\memory_lean_dection_demo\memory_lean_dection_demo.cpp(28) : {91} normal block at 0x003A8F08, 4 bytes long.
- Data: < > CD CD CD CD
- e:\project\memory_lean_dection_demo\memory_lean_dection_demo\memory_lean_dection_demo.cpp(27) : {90} normal block at 0x003A8EC8, 4 bytes long.
- Data: < > 0A 00 00 00
- Object dump complete.
- The program '[0x1318] memory_lean_dection_Demo.exe: Native' has exited with code 0 (0x0).
- 如果没开宏:
- //malloc memory leak detect
- //#define _CRTDBG_MAP_ALLOC
- #include <stdlib.h>
- #include <crtdbg.h>
- //new memory leak detect
- //#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
- Output检测的结果如下:
- Detected memory leaks!
- Dumping objects ->
- {91} normal block at 0x003A8F08, 4 bytes long.
- Data: < > CD CD CD CD
- {90} normal block at 0x003A8EC8, 4 bytes long.
- Data: < > 0A 00 00 00
- Object dump complete.
- The program '[0x1398] memory_lean_dection_Demo.exe: Native' has exited with code 0 (0x0).
#include "stdafx.h"
#ifdef _DEBUG
//malloc memory leak detect
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
//new memory leak detect
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
inline void EnableMemLeakCheck()
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
//_CrtDumpMemoryLeaks();
}
#endif
int _tmain(int argc, _TCHAR* argv[])
{
//_CrtSetBreakAlloc(91);
int* arrValue= new int(10);
int* pValueVec = (int*)malloc(4);
#ifdef _DEBUG
EnableMemLeakCheck();
#endif
return 0;
}
Output浮动面板的检测到的内存泄露的信息如下:(红色代表泄露的代码位置,通过双击该行可以直接定位到源码处)
Detected memory leaks!
Dumping objects ->
e:\project\memory_lean_dection_demo\memory_lean_dection_demo\memory_lean_dection_demo.cpp(28) : {91} normal block at 0x003A8F08, 4 bytes long.
Data: < > CD CD CD CD
e:\project\memory_lean_dection_demo\memory_lean_dection_demo\memory_lean_dection_demo.cpp(27) : {90} normal block at 0x003A8EC8, 4 bytes long.
Data: < > 0A 00 00 00
Object dump complete.
The program '[0x1318] memory_lean_dection_Demo.exe: Native' has exited with code 0 (0x0).
如果没开宏:
//malloc memory leak detect
//#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
//new memory leak detect
//#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
Output检测的结果如下:
Detected memory leaks!
Dumping objects ->
{91} normal block at 0x003A8F08, 4 bytes long.
Data: < > CD CD CD CD
{90} normal block at 0x003A8EC8, 4 bytes long.
Data: < > 0A 00 00 00
Object dump complete.
The program '[0x1398] memory_lean_dection_Demo.exe: Native' has exited with code 0 (0x0).
Reference:
2.基于 crt debug 实现的 Windows 程序内存泄漏检测工具
3.CrtDumpMemoryLeaks和_CrtSetBreakAlloc 和_CrtSetDbgFlag
4.内存泄漏检测工具--Visual Leak Detector (VLD)
5.__FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)
6.浅谈C++中内存泄漏的检测 http://www.cnblogs.com/phinecos/archive/2009/10/29/1592604.html