使用调试器和CRT库来查找内存泄漏

来源:互联网 发布:c sql查询语句怎么写 编辑:程序博客网 时间:2024/05/21 18:43

置内存泄漏检测

检测内存泄漏的基本工具是调试器和CRT调试堆函数。了使用调试堆函数,在你的程序中你必含有下面的明:

#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>

#include明必明。如果你改序,你所用的函数可能不能正常工作。包含crtdbg.h_malloc_dbg_free_dbgmallocfree函数映射到测试版中,它可以跟踪内存的分配和放。这种映射仅仅在一个测试体系中(也就是仅仅_DEBUG被定)放的体系使用通常的mallocfree功能。

#define明映射CRT堆函数的低版本到相测试版本。明是不需要的,但是没有它,内存泄漏含有的只是没有多大用的信息。

一旦你已增加了才的明,你能在你的程序中包含下面的明来放内存信息:

_CrtDumpMemoryLeaks();

当你在调试情况下运行你的程序,在出窗口的Debug 标签处_CrtDumpMemoryLeaks出内存泄漏的信息。内存泄漏信息似下面这样

Detected memory leaks!

Dumping objects ->

C:/PROGRAM FILES/VISUAL STUDIO/MyProjects/leaktest/leaktest.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.

如果你没有用#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.

像你所知道的,当_CRTDBG_MAP_ALLOC被定义时_CrtDumpMemoryLeaks了你更多的有用信息。如果_CRTDBG_MAP_ALLOC没有被定,那将向你如下示:

  • 内存分配数(花括号内)
  • 型(normalclient或者CRT
  • 以十六制格式定位的内存
  • 以字节计的大小
  • 第一个十六字的内容(也可以用十六制)

当定_CRTDBG_MAP_ALLOC候,示的内容也向你展了出泄漏内存所分配地方的文件。在文件名之后括号内的数字(20,以此例)是文件内的行数。如果你双包含行数和文件名的出行,

C:/PROGRAM FILES/VISUAL STUDIO/MyProjects/leaktest/leaktest.cpp(20) : {18} normal block at 0x00780E80, 64 bytes long.

将会跳到源文件中内存被分配地方的行(在上面的情况下,leaktest.cpp的行号20)。选择输出行并按F4将有同的效果。

使用_CrtSetDbgFlag

如果你的程序是在同一各地方存在,那么调_CrtDumpMemoryLeaks非常容易的。但是,如果你的程序需要在多个位置退出么办?在一个可能的出口如果不_CrtDumpMemoryLeaks,你可在你的程序包含下面的用:

_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

当你的程序退出明自_CrtDumpMemoryLeaks。你必须设置两个位域,_CRTDBG_ALLOC_MEM_DF_CRTDBG_LEAK_CHECK_DF,像以前明的一

内存模

像早期声明的一,内存泄漏信息鉴别泄漏内存的一个模一个普通的模、一个客或者一个CRT实际上,普通的模和客是你可能留心的唯一型。

  • 一个普通模(normal block)是由你的程序分配的普通内存。
  • 一个客(client block)是一特殊的内存模,它由于需要一个析构函数的象而被Microsoft Foundation Classes (MFC)所使用。MFC new操作子建立一个普通模或者一个客,来适合被建的模
  • 一个CTR是由CRT提供自己使用而分配的内存模CRT库对这些模管理自己的去分配,因此你不可能在内存泄漏告中注意到些,除非有些地方有重的错误(例如,CRT)。

在内存泄漏信息中有两你从来没有见过的模块类型:

  • free block)是一放的内存模
  • Ignore block是你已特殊标记过以至于在内存泄漏告中不会出的模

CRT

像以前描写的一,按默方式,_CrtDumpMemoryLeaks卸内存泄漏信息到出窗口的Debug窗格。你可以运用_CrtSetReportMode重新置它到堆存,到另一个位置。如果你使用一个,它可能重新出到另一个位置。在这种情况下,你能利用下面的明来出位置回到出窗口:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

于使用_CrtSetReportMode出信息到另一个位置,要看Visual C++文件的_CrtSetReportMode

在内存分配数目处设置一个断点

在内存泄漏告中的文件名和行号可告你泄漏的内存在那里被分配,但是了解内存在那里分配问题是充分的。在一个程序运行程中,常是一个分配将会被用很多次,但是它可能在某次用中泄漏内存。了确定问题,你必不但知道泄漏的内存在那里分配,要知道泄漏生的条件。你来,使它成可能的那条信息是内存分配号。当那些被示的候,文件名和行号之后,是在curly brace中出的数。例如,在下面的出中,“18”是内存分配号。它的意思是泄漏的内存是你程序中内存分配的第十八个模

Detected memory leaks!

Dumping objects ->

C:/PROGRAM FILES/VISUAL STUDIO/MyProjects/leaktest/leaktest.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.

CRT库计算在程序运行期分配的所用内存模,包括CRT自己分配的内存或者MFC的其它模。因此有分配号n的一个象是在你的程序中分配的第n象,但不可能是由代分配的第n象。(在大部分情况下,它是不会的。)

你可以利用分配号在内存分配的地方置一个断点。了做些,你可以距离你的程序始很近置一个位置断点。当你的程序在那一点,你能QuickWatch对话框或者Watch窗口这样一个位置断点。例如,在Watch窗口中,在Name栏键入下面的表达式:

_crtBreakAlloc

如果你正在用CRT的多线程的dynamic-link library (DLL)版本,你必含有上下文操作符,像明的:

{,,msvcrtd.dll}_crtBreakAlloc

在,按RETURN调试用并且把果放置在Value。如果你在内存分配程中没有置任何断点,那么这是-1。使用你想中断内存分配的分配数来代替Value表中的——例如,18 去中断早期在程中展的分配.

当你在你感趣的内存分配处设置断点之后,你能够继续调试。在与从前相同的条件下,运行程序一定要小心,因而分配的序不会改。当你的程序在一个特殊的内存分配点中断的候,你能够查Call Stack窗口和其他的测试信息来确定在此条件下内存的分配。如果需要的,你可以继续从那一点程序,以至于了解象到底生了什事,同时还可能确定了没有正确地被去分配。(对对置一个数据断点是很有帮助的。)

然在调试器中置内存分配断点通常更加容易,但是如果你喜,你可以在你的代置它了在你的代置一个内存分配断点,可以增加这样一行(于第十八个内存分配):

_crtBreakAlloc = 18;

一个选择,你可以使用有相同效果的_CrtSetBreakAlloc函数。

_CrtSetBreakAlloc(18);

内存状

定位内存泄漏的另一个方法就是在关键对应程序的内存状做快照。CRT提供了一个型,_CrtMemState。你可以使用它来存内存状的一个快照。

_CrtMemState s1, s2, s3;

了在特定点内存状态进行快照,可以传递一个_CrtMemState构到he _CrtMemCheckpoint函数。此函数用当内存状的一个快照来填充此构:

_CrtMemCheckpoint( &s1 );

你可以通过传递构到_CrtMemDumpStatistics函数来_CrtMemState构的任意点的内容:

_CrtMemDumpStatistics( &s3 );( &s1 );

此函数打印出似于下面这样的一堆内存分配信息:

0 bytes in 0 Free Blocks.

0 bytes in 0 Normal Blocks.

3071 bytes in 16 CRT Blocks.

0 bytes in 0 Ignore Blocks.

0 bytes in 0 Client Blocks.

Largest number used: 3071 bytes.

Total allocations: 3764 bytes.

了确定一个内存泄漏是否在一中出,你可以在此前和此内存状作快照,然后用_CrtMemDifference

_CrtMemCheckpoint( &s1 );

// memory allocations take place here

_CrtMemCheckpoint( &s2 );

 

if ( _CrtMemDifference( &s3, &s1, &s2) )

   _CrtMemDumpStatistics( &s3 );

像名字暗示的一_CrtMemDifference两个内存状(最先的两个参数)并且生一个不同于两个状果(第三个参数)。在你的程序始和_CrtMemCheckpoint用和使有_CrtMemDifference来比较结为检测内存泄漏提供了另一方法。如果一个泄漏被检测到,那可以使用_CrtMemCheckpoint用来分割你的程序并且使用二元binary search technique来定位泄漏。

 

原创粉丝点击