引用原文地址

用CRT查找内存泄漏,CRT查找内存泄漏

引用原文地址

 

1. 在program中严格按上面顺序include

  1 #define _CRTDBG_MAP_ALLOC
  2 #include <stdlib.h>
  3 #include <crtdbg.h>

 

2. 必须是Debug版的build

Q : LiteServer遍Debug可能会遇见一些问题

A : 可以用来阐明Memcheck是还是不是有误报。

   
可以在对应的地址处下断点(会频仍断在malloc上,要求基于size下标准断点)

Q : code在Release和Debug版下可能会不同,最后可能会油然则生一个有memory
leak一个未曾

 

3. “#define _CRTDBG_MAP_ALLOC”这么些宏不可能大概,否则memory
leak的dump会缺乏一些细节(如leak的code地方消息)

 

4. 在app exit前,可以调用这一个function打印memory leak report

_CrtDumpMemoryLeaks();

Q : 若是是大局或静态obj,在exit前其还未释放,此时report不会导致误报吗?

A :不会

 

5. 如若app有多个exits,你是不须求call
_CrtDumpMemoryLeaks()在种种exit地点的。在app伊始的任务call下边这些_CrtSetDbgFlag(),其会活动在种种exit的岗位自动call
_CrtDumpMemoryLeaks()

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
);

 

6. 默许情形下,memory leak的report会在VS Studio
Debug窗的Output窗口中,可以用_CrtSetReportMode()将其重定向到其余职位。

 

7. Report格式

Detected memory leaks!

Dumping objects ->

c:\users\username\documents\projects\leaktest\leaktest.cpp(20) : {18}               //{18} : memory分配序号 

normal block at 0x00780E80, 64 bytes long.                                         //64 bytes : block的大小(并不是分配时指定的大小,因为分配的heap由于会添加堆头堆尾等额外信息,会比分配时指定的size要大) 

Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

 

Q : 发现就算如约第一条中的定义,也不会输出memory leak的行信息。

A :
那几个crtdbg对new处理不佳,其block的地点只会new调用macro的地方,可用如下宏DBG_NEW来代替new,以打印出相应的行音信

#ifdef _DEBUG

    #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )

    // Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the 

    // allocations to be of _CLIENT_BLOCK type 

#else

    #define DBG_NEW new

#endif

 

Q : 需要替换所有的源码,而且第三方库怎么做?

Q : 没有栈回溯音讯,多层调用怎么查找源头音讯?

A : 
Debug,在app入口断下后,在watch窗口输入”_crtBreakAlloc”(如若”Runtime
Library”是”/MD”,则还须求丰硕”{,,ucrtbased.dll}_crtBreakAlloc”),这么些值应该是”-1″,修改成detect到的memory
leak的分红序号(如7中的{18}),当分配该大小的memory时就会断下来(注意,重跑后的规格要和率先次得到分配序号的同样)。

用CRT查找内存泄漏,关于MFC下检查和扫除内存走漏的技术。    其它,在code中也得以直接指定:

_crtBreakAlloc = 18;

    or :

_CrtSetBreakAlloc(18);

 

8. Test

1> code

#include <memory>

std ::tr1 ::shared_ptr <int >   sp_nTest;

void  Test ()
{
      sp_nTest. reset( new int( 0x88));

      //memory leak
      int*  pnTest = new int( 0xCC);

      void* pMalloc = malloc( sizeof( int));
}

 

2> result

Detected memory leaks!

Dumping objects ->

d:\codes\vs2010\test\detectmemleak\console\test.cpp(14) : {65} normal block at 0x007B18A8, 4 bytes long.

Data: <    > CD CD CD CD

{64} normal block at 0x007B4F90, 4 bytes long.

Data: <    > CC 00 00 00

Object dump complete.

甲申革命部分是new出来的memory leak,可知并不会报出相应的code的行号

引用原文地址
: 1.
在program中严厉按上面顺序include 1 #defin…

引用原文地址

摘要
正文分析了Windows环境使用MFC调试内存走漏的技巧,介绍了在Windows环境下用VC++查找,定位和扫除内存走漏的格局技巧。

要害词:VC++;CRT 调试堆函数;试探法。

 

 

编译环境
VC++6.0
技巧原理
检测内存泄漏的紧要工具是调试器和 CRT
调试堆函数。若要启用调试堆函数,请在先后中概括以下语句:
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
注意 #include
语句必须接纳上文所示逐项。假若更改了逐一,所运用的函数可能不可能正确工作。

1. 在program中严苛按下边顺序include

1. 在program中严谨按上边顺序include

经过包蕴 crtdbg.h,将 malloc 和 free
函数映射到其“Debug”版本_malloc_dbg
和_free_dbg,这几个函数将跟踪内存分配和假释。此映射只在调试版本(在里边定义了
_DEBUG)中爆发。公布版本选用普通的 malloc 和 free 函数。

  1 #define _CRTDBG_MAP_ALLOC
  2 #include <stdlib.h>
  3 #include <crtdbg.h>
  1 #define _CRTDBG_MAP_ALLOC
  2 #include <stdlib.h>
  3 #include <crtdbg.h>

#define 语句将 CRT
堆函数的基版本映射到相应的“Debug”版本。并非绝对必要该语句,但假设没有该语句,内存泄漏转储包蕴的有用新闻将较少。

 

 

在添加了位置所示语句之后,可以透过在程序中包蕴以下语句来转储内存泄漏音讯:
_CrtDumpMemoryLeaks();
当在调试器下运行程序时,_CrtDumpMemoryLeaks
将在“输出”窗口中显得内存泄漏音讯。内存泄漏音信如下所示:
Detected memory leaks!

2. 必须是Debug版的build

2. 必须是Debug版的build

Dumping objects ->

Q : LiteServer遍Debug可能会遇上一些难题

Q : LiteServer遍Debug可能会碰到有的难题

C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) : {18}
normal block at 0x00780E80, 64 bytes long.

A : 可以用来验证Memcheck是不是有误报。

A : 可以用来证实Memcheck是还是不是有误报。

Data: <        > CD CD CD CD CD CD CD CD CD CD CD CD CD CD
CD CD
Object dump complete.
假定不选用 #define _CRTDBG_MAP_ALLOC 语句,内存泄漏转储如下所示:
Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

   
可以在对应的地点处下断点(会频仍断在malloc上,必要基于size下标准断点)

   
能够在相应的地点处下断点(会频仍断在malloc上,要求根据size下标准断点)

未定义 _CRTDBG_MAP_ALLOC 时,所浮现的会是:

Q : code在Release和Debug版下可能会不均等,最终可能会冒出一个有memory
leak一个从未

Q : code在Release和Debug版下可能会不等同,最终可能会出现一个有memory
leak一个从来不

内存分配编号(在大括号内)。
块类型(普通、客户端或 CRT)。
十六进制格局的内存地方。
以字节为单位的块大小。
前 16 字节的始末(亦为十六进制)。
定义了 _CRTDBG_MAP_ALLOC
时,还会来得在里头分配泄漏的内存的公文。文件名后括号中的数字(本示例中为
20)是该文件内的行号。

 

 

转到源文件中分配内存的行

3. “#define _CRTDBG_MAP_ALLOC”那个宏无法简单,否则memory
leak的dump会缺乏一些细节(如leak的code地点音讯)

3. “#define _CRTDBG_MAP_ALLOC”这一个宏不可以大概,否则memory
leak的dump会缺乏一些细节(如leak的code地点音信)

在”输出”窗口中双击包括文件名和行号的行。
-或-

 

 

在”输出”窗口中拔取包罗文件名和行号的行,然后按 F4 键。
_CrtSetDbgFlag

4. 在app exit前,可以调用那么些function打印memory leak report

4. 在app exit前,可以调用那一个function打印memory leak report

如果程序总在同样位置退出,则调用 _CrtDumpMemoryLeaks
丰盛便利,但假诺程序可以从多少个地点退出该如何是好呢?不要在种种可能的谈话放置一个对
_CrtDumpMemoryLeaks 的调用,可以在程序开端席卷以下调用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
);

_CrtDumpMemoryLeaks();

_CrtDumpMemoryLeaks();

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

Q : 要是是大局或静态obj,在exit前其还未释放,此时report不会促成误报吗?

Q : 假使是全局或静态obj,在exit前其还未释放,此时report不会导致误报吗?

说明
在VC++6.0的环境下,不再要求卓绝的丰硕
#澳门金沙国际 ,define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

A :不会

A :不会

只需求按F5,在调节情状下运作,程序退出后在”输出窗口”可以见见有无内存走漏。若是出现
Detected memory leaks!
Dumping objects ->

 

 

就有内存走漏。

5. 比方app有多少个exits,你是不要求call
_CrtDumpMemoryLeaks()在各类exit地方的。在app初叶的地点call上面那么些_CrtSetDbgFlag(),其会自动在各样exit的职位自动call
_CrtDumpMemoryLeaks()

5. 一旦app有三个exits,你是不必要call
_CrtDumpMemoryLeaks()在种种exit地点的。在app伊始的职责call上边那么些_CrtSetDbgFlag(),其会活动在各种exit的岗位自动call
_CrtDumpMemoryLeaks()

规定内存走漏的地点
基于内存走漏的报告,有三种消除的方法:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
);

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF
);

第一种相比不难,就是曾经把内存走漏映射到源文件的,可以直接在”输出”窗口中双击包蕴文件名和行号的行。例如
Detected memory leaks!
Dumping objects ->
C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) : {18}
normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20)

 

 

就是源文件名称和行号。

6. 默许意况下,memory leak的report会在VS Studio
Debug窗的Output窗口中,可以用_CrtSetReportMode()将其重定向到此外岗位。

6. 默许处境下,memory leak的report会在VS Studio
Debug窗的Output窗口中,可以用_CrtSetReportMode()将其重定向到其余地点。

第二种相比较费心,就是不可以映照到源文件的,唯有内存分配块号。
Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

 

 

  那种意况本身动用一种”试探法”。由于内存分配的块号不是一定不变的,而是每一遍运行都是生成的,所以跟踪起来很勤奋。然而我意识即使内存分配的块号是转变的,可是变化的块号却连年这一个,也就是说多运行两次,内存分配的块号很可能会另行。因而那就是”试探法”的根基。
先在调试情形下运作三遍程序,观看内存分配的块号是哪多少个值;
选取出现次数最多的块号来设断点,在代码中设置内存分配断点:
充分如下一行(对于第 18 个内存分配):
_crtBreakAlloc = 18;
或者,能够行使具有同样效果的 _CrtSetBreakAlloc 函数:
_CrtSetBreakAlloc(18);
在调节景况下运行序,在断点停下时,打开”调用堆栈”窗口,找到相应的源代码处;

7. Report格式

7. Report格式

剥离程序,寓目”输出窗口”的内存走漏报告,看其实内存分配的块号是还是不是和预设值相同,若是一致,就找到了;即便不相同,就再度步骤3,直到相同。
末尾就是依据具体景况,在适宜的义务释放所分配的内存。

Detected memory leaks!

Dumping objects ->

c:\users\username\documents\projects\leaktest\leaktest.cpp(20) : {18}               //{18} : memory分配序号 

normal block at 0x00780E80, 64 bytes long.                                         //64 bytes : block的大小(并不是分配时指定的大小,因为分配的heap由于会添加堆头堆尾等额外信息,会比分配时指定的size要大) 

Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

 
Detected memory leaks!

Dumping objects ->

c:\users\username\documents\projects\leaktest\leaktest.cpp(20) : {18}               //{18} : memory分配序号 

normal block at 0x00780E80, 64 bytes long.                                         //64 bytes : block的大小(并不是分配时指定的大小,因为分配的heap由于会添加堆头堆尾等额外信息,会比分配时指定的size要大) 

Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

 

Q : 发现就是如约第一条中的定义,也不会输出memory leak的行新闻。

Q : 发现就是依据第一条中的定义,也不会输出memory leak的行音讯。

A :
那一个crtdbg对new处理不佳,其block的地点只会new调用macro的地方,可用如下宏DBG_NEW来替代new,以打印出相应的行新闻

A :
这些crtdbg对new处理不佳,其block的地方只会new调用macro的地址,可用如下宏DBG_NEW来取代new,以打印出相应的行音讯

#ifdef _DEBUG

    #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )

    // Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the 

    // allocations to be of _CLIENT_BLOCK type 

#else

    #define DBG_NEW new

#endif
#ifdef _DEBUG

    #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )

    // Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the 

    // allocations to be of _CLIENT_BLOCK type 

#else

    #define DBG_NEW new

#endif

 

 

Q : 须要替换所有的源码,而且第三方库咋办?

Q : 必要替换所有的源码,而且第三方库如何做?

Q : 没有栈回溯音讯,多层调用怎么查找源头音信?

Q : 没有栈回溯信息,多层调用怎么查找源头音讯?

A : 
Debug,在app入口断下后,在watch窗口输入”_crtBreakAlloc”(即使”Runtime
Library”是”/MD”,则还亟需充分”{,,ucrtbased.dll}_crtBreakAlloc”),那么些值应该是”-1″,修改成detect到的memory
leak的分配序号(如7中的{18}),当分配该大小的memory时就会断下来(注意,重跑后的标准化要和率先次拿走分配序号的同一)。

A : 
Debug,在app入口断下后,在watch窗口输入”_crtBreakAlloc”(倘使”Runtime
Library”是”/MD”,则还必要充足”{,,ucrtbased.dll}_crtBreakAlloc”),那一个值应该是”-1″,修改成detect到的memory
leak的分红序号(如7中的{18}),当分配该大小的memory时就会断下来(注意,重跑后的口径要和第四遍拿走分配序号的一致)。

    其余,在code中也足以一向指定:

    其它,在code中也足以一贯指定:

_crtBreakAlloc = 18;

    or :

_CrtSetBreakAlloc(18);
_crtBreakAlloc = 18;

    or :

_CrtSetBreakAlloc(18);

 

 

8. Test

8. Test

1> code

1> code

#include <memory>

std ::tr1 ::shared_ptr <int >   sp_nTest;

void  Test ()
{
      sp_nTest. reset( new int( 0x88));

      //memory leak
      int*  pnTest = new int( 0xCC);

      void* pMalloc = malloc( sizeof( int));
}
#include <memory>

std ::tr1 ::shared_ptr <int >   sp_nTest;

void  Test ()
{
      sp_nTest. reset( new int( 0x88));

      //memory leak
      int*  pnTest = new int( 0xCC);

      void* pMalloc = malloc( sizeof( int));
}

 

 

2> result

2> result

Detected memory leaks!

Dumping objects ->

d:\codes\vs2010\test\detectmemleak\console\test.cpp(14) : {65} normal block at 0x007B18A8, 4 bytes long.

Data: <    > CD CD CD CD
Detected memory leaks!

Dumping objects ->

d:\codes\vs2010\test\detectmemleak\console\test.cpp(14) : {65} normal block at 0x007B18A8, 4 bytes long.

Data: <    > CD CD CD CD

{64} normal block at 0x007B4F90, 4 bytes
long.

{64} normal block at 0x007B4F90, 4 bytes
long.

Data: <    > CC 00 00 00

Object dump complete.
Data: <    > CC 00 00 00

Object dump complete.

青色部分是new出来的memory leak,可知并不会报出相应的code的行号

革命部分是new出来的memory leak,可知并不会报出相应的code的行号

相关文章