C++检查内存泄露

标签: 检查 内存泄露 | 发表时间:2013-01-11 12:31 | 作者:iuhsihsow
出处:http://blog.csdn.net

说明,我使用的ide是vs2008



1. 工程设置为debug

内存泄露的检测一般在debug模式下进行


2.在需要检查内存泄露的cpp头部加上

#ifdef	_DEBUG
 #define _CRTDBG_MAP_ALLOC
 #include <stdlib.h>
 #include <crtdbg.h>
 	#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)
 #endif

3.代码中插入这么一句话

EnableMemLeakCheck();

inline void EnableMemLeakCheck()
 {
 	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
 }
 

4.然后就可以在输出中看泄露情况了

举个例子,例子中我用newEx表示的上述宏定义中的new

int _tmain(int argc, _TCHAR* argv[])
 {
 	EnableMemLeakCheck();
 	int num = 10;
 	byte **p = newEx byte *[num];
 	for (int i = 0; i < num; i ++)
 	{
 		Sleep(1);
 		*p = newEx byte[i];
 	}
 
 	long *pl = newEx long[100];
 
 	while(1)
 	{
 		Sleep(100);
 	}
 	return 0;
 }

输出中显示的内容(debug下运行程序,然后点叉叉关闭程序)

memory leaks!
 Dumping objects ->
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(101) : {124} normal block at 0x00295CB8, 400 bytes long.
  Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {122} normal block at 0x00294C30, 9 bytes long.
  Data: <         > CD CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {121} normal block at 0x00294BE8, 8 bytes long.
  Data: <        > CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {120} normal block at 0x00299F88, 7 bytes long.
  Data: <       > CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {119} normal block at 0x00299F40, 6 bytes long.
  Data: <      > CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {118} normal block at 0x00299EF8, 5 bytes long.
  Data: <     > CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {117} normal block at 0x00299EB8, 4 bytes long.
  Data: <    > CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {116} normal block at 0x00299E78, 3 bytes long.
  Data: <   > CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {115} normal block at 0x00299E38, 2 bytes long.
  Data: <  > CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {114} normal block at 0x00299DF8, 1 bytes long.
  Data: < > CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : {113} normal block at 0x00299DB8, 0 bytes long.
  Data: <> 励p
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(88) : {112} normal block at 0x00299D50, 40 bytes long.
  Data: <0L)             > 30 4C 29 00 CD CD CD CD CD CD CD CD CD CD CD CD 
 Object dump complete.


有文件名和行号,先申请的后释放。


扩展:

实际上是使用了另外的new,在dbgnew.cpp中,列一个例子说明:


void *__CRTDECL operator new[](
         size_t cb,
         int nBlockUse,
         const char * szFileName,
         int nLine
         )
         _THROW1(_STD bad_alloc)
 {
     void *res = operator new(cb, nBlockUse, szFileName, nLine );
 
     RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
 
     return res;
 }
 


注意,const char *szFileName可以使用__file__也可以使用自定义的类,经过重载为char*(感谢老马提供代码)

例如:

char new_index_recorder_file_name[1024 * 1024][256];
 
 
 
 class new_index_recorder{
 
 public:
 
 	new_index_recorder(char* file, int line) : file(file), line(line){
 
 
 
 	} 
 
 	operator char*(){
 
 		static unsigned int index;
 
 		sprintf(new_index_recorder_file_name[index], "%s(%d) : %d ", file, line, index++);
 
 		return  new_index_recorder_file_name[index];
 
 	}
 
 private:
 
 	char* file;
 
 	int line; 
 
 };


当然,也可以用函数来返回char*指针

int g_count = 0;
 
 class OperNew
 {
 public:
 	OperNew()
 	{	
 		g_count ++;
 		pC = new char[20];
 		memset(pC, 0, 10);
 		sprintf(pC, "No.%d", g_count);
 	}
 	char* GetChar()
 	{
 		return pC;
 	}
 private:
 	char * pC ;
 };

这样就能返回自定义的内容了。本次的返回加上了一个构造时候的序号,当然也可以添加时间等。结果如下:

e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(95) : 11 (95) : {123} normal block at 0x002B4C78, 400 bytes long.
  Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 10 (92) : {122} normal block at 0x002B4C30, 9 bytes long.
  Data: <         > CD CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 9 (92) : {121} normal block at 0x002B4BE8, 8 bytes long.
  Data: <        > CD CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 8 (92) : {120} normal block at 0x002B9F88, 7 bytes long.
  Data: <       > CD CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 7 (92) : {119} normal block at 0x002B9F40, 6 bytes long.
  Data: <      > CD CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 6 (92) : {118} normal block at 0x002B9EF8, 5 bytes long.
  Data: <     > CD CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 5 (92) : {117} normal block at 0x002B9EB8, 4 bytes long.
  Data: <    > CD CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 4 (92) : {116} normal block at 0x002B9E78, 3 bytes long.
  Data: <   > CD CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 3 (92) : {115} normal block at 0x002B9E38, 2 bytes long.
  Data: <  > CD CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 2 (92) : {114} normal block at 0x002B9DF8, 1 bytes long.
  Data: < > CD 
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(92) : 1 (92) : {113} normal block at 0x002B9DB8, 0 bytes long.
  Data: <> h鴌
 e:\project\test\test_mem_leak\test_mem_leak\test_mem_leak.cpp(88) : 0 (88) : {112} normal block at 0x002B9D50, 40 bytes long.
  Data: <0L+             > 30 4C 2B 00 CD CD CD CD CD CD CD CD CD CD CD CD 
 Object dump complete.
 程序“[8796] test_MEM_LEAK.exe: 本机”已退出,返回值为 -1073741510 (0xc000013a)。


小提示:

将输出文件拷贝到UE中,然后查找泄露行号出现的次数,可以计算出泄露的数目。



作者:iuhsihsow 发表于2013-1-11 12:31:12 原文链接
阅读:73 评论:0 查看评论

相关 [检查 内存泄露] 推荐:

C++检查内存泄露

- - CSDN博客推荐文章
说明,我使用的ide是vs2008. 内存泄露的检测一般在debug模式下进行. 2.在需要检查内存泄露的cpp头部加上. 4.然后就可以在输出中看泄露情况了. 举个例子,例子中我用newEx表示的上述宏定义中的new. 输出中显示的内容(debug下运行程序,然后点叉叉关闭程序).   Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD .

关于内存泄露

- - 银河里的星星
valgrind 详细说明  http://www.cnblogs.com/wangkangluo1/archive/2011/07/20/2111273.html. 近期Imgsrc一处内存泄露问题的查找和解决  http://rdc.taobao.com/blog/cs/?p=1651.

ios Instruments 内存泄露

- - ITeye博客
虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在. 这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置的使用. 本文假设你已经比较熟悉Obj-C的内存管理机制. 实验的开发环境:XCode 4.5.2.

Java的内存泄露

- - Java译站
Java有垃圾回收,因此不会出现内存泄露. 尽管Java的确有垃圾回收器来回收那些不用的内存块,但你不要指望它能够点铁成金. GC减轻了开发人员肩上的负担,而原本的那些工作非常容易出错,不过并不是所有内存分配的问题它都能够解决. 更糟糕的是,Java的设计允许它可以欺骗GC,使得它能够保留一些程序已经不再使用的内存.

ThreadLocal的内存泄露

- - zzm
ThreadLocal的目的就是为每一个使用ThreadLocal的线程都提供一个值,让该值和使用它的线程绑定,当然每一个线程都可以独立地改变它绑定的值. 如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序.. 关于的ThreadLocal更多内容,请参考《 ThreadLocal》.

Android 内存泄露总结

- - CSDN博客推荐文章
Android 内存泄漏总结. 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题. 内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收. 最近自己阅读了大量相关的文档资料,打算做个 总结 沉淀下来跟大家一起分享和学习,也给自己一个警示,以后 coding 时怎么避免这些情况,提高应用的体验和质量.

解决php内存泄露问题

- - 鲁塔弗的博客
这是08年写的一份文档,我当时在一家网站刚接手做技术负责人,网站每天大概有60万ip/300万pv的访问,网站产品很复杂,代码结构差,开发工程师来来去去,代码只能只读了. 突然有一天开始频繁出现php-fpm进程耗光内存和cpu占有率飙升,前端频繁出现504错误. php-fpm进程耗光内存 这个就是传说中的内存泄露,所谓内存泄露,是指进程在运行过程中,内存占用率逐步上升而不释放,导致系统可用内存越来越少的情况.

使用MAT分析内存泄露

- - Taobao QA Team
对于大型服务端应用程序来说,有些内存泄露问题很难在测试阶段发现,此时就需要分析JVM Heap Dump文件来找出问题. 随着单机内存越来越大,应用heap也开得越来越大,动辄十几G的Dump也不足为奇了. 要快速分析,快速定位问题就必须有给力的工具帮忙,下面我来介绍下常用内存分析工具. JDK自带的一个工具,是JVM Heap导出的必备工具.

c++内存泄露检测(简单)

- - CSDN博客推荐文章
C++ 的一个 比较晦涩难懂的特点是你可以重载 new 操作符,并且你甚至可以给它附加参数. 通常,操作符 new 只接受拟分配对象的大小:.   但你也可以随心所欲附加参数来重载 new 操作符,只要在调用 new 时候提供这些参数即可. 在各种应用程序向导(App Wizards)中,这 是 MFC 所做的事情.

如何查找Android内存泄露

- - HelloSure
eclipse中可以使用DDMS的heap视图来看data object的total size项. android studio中直接观察memory monitor. (Memory Monitor是android studio自带的,不需要额外安装,这个工具显然更直观一些). 个人觉得这种方式可以作为查找内存泄露的突破口,如果发现一些异常,比如抖动大说明GC频繁,或比如GC对内存释放不明显,或比如GC之后内存并没有稳定在一定的范围之内,则可能是有内存泄露问题,可以接下去分析.