分类

  • 软件天地

  • 用VC++ debugger检测和隔离内存泄漏‖
    debugger 和 CRT库提供了
    内存的能力是C/C++程序语言的
    一系列有效的检测和鉴定内存泄
    重要特色之一。Visual C++
    漏的工具。

      设置内存泄漏检测

      检测内存泄漏的基本工
    中你必须含有下面的说明:
    具是调试器和CRT调试堆函数。

    为了使用调试堆函数,在你的程序


      #define _CRTDBG_MAP_
    ALLOC#include #include

      #include说明必须按顺序说明。如果
    crtdbg.h的_malloc_dbg和 _free_dbg将
    的分配和释放。这种映射仅仅在一个测试
    。释放的体系使用通常的malloc和 free
    改变了顺序,所用的函数可能不能正常工作。包含
    malloc和free函数映射到测试版中,它可以跟踪内存
    体系中发生(也就是说,仅仅当_DEBUG被定义的时候)
    功能。

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

      一旦你已经增加了刚才

    的说明,你能够通过在你的程序

    中包含下面的说明来释放内存信息

      _CrtDumpMemoryLeaks();                                  

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

      Detected memory leaks!                                  
      Dumping objects ->

      C:PROGRAM FILESVIS
    normal block at
    UAL STUDIOMyProjectsleakte

    stleaktest.cpp(20) : {18}

      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被定义时,_Cr
    _CRTDBG_MAP_ALLOC没有被定义,那么将
    tDumpMemoryLeaks给了你更多的有用信息。如果
    向你如下显示:

      内存分配数值(花括号内)                                                      
      模块的类型(normal、client或者CRT)                            
      以十六进制格式定位的内存                                                      
      以字节计模块的大小                                                            
      第一个十六字节的内容(也可以用十六进制)                                      
      当定义了_CRTDBG_MAP_ALLOC的时候
    的文件。在文件名之后括号内的数字(20
    数值和文件名的输出行,
    ,显示的内容也向你展现了出现泄漏内存所分配地方
    ,以此为例)是文件内的行数值。如果你双击包含行

      C:PROGRAM FILESVIS
    normal block at
    UAL STUDIOMyProjectsleakte

    stleaktest.cpp(20) : {18}

      0x00780E80, 64 bytes long.                          

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


      使用_CrtSetDbgFlag

      如果你的程序总是在同一各地方存在
    是,如果你的程序需要在多个位置退出该
    _CrtDumpMemoryLeaks,你可在你的程序
    ,那么调用_CrtDumpMemoryLeaks时非常容易的。但
    怎么办?在每一个可能的出口处如果不调用
    开始处包含下面的调用:
      _CrtSetDbgFlag( _CRT
    DBG_ALLOC_MEM_DF | _CRTDBG_L
    EAK_CHECK_DF);
      当程序退出时,这个说
    _CRTDBG_ALLOC_MEM_DF和 _
    明自动地调用_CrtDumpMemoryLe
    CRTDBG_LEAK_CHECK_DF。
    aks。你必须设置两个位域,


      翻译内存模块的类型

      内存泄漏信息鉴别泄漏内存的每一个
    CRT模块。实际上,普通的模块和客户模
    模块作为一个普通的模块、一个客户模块或者一个
    块是你可能留心的唯一类型。
      一个普通模块(normal block)是由你的程序分配的普通内存。          
      一个客户模块(client
    被Microsoft Foundation C
    客户模块,来适合被创建的
    block)是一种特殊的内存模块,
    lasses (MFC)所使用。MFC new
    模块。
    它由于需要一个析构函数的对象而
    操作子建立一个普通模块或者一个

      一个CTR模块是由CRT库提供自己使用
    去分配,因此你不可能在内存泄漏报告中
    CRT库崩溃)。
    而分配的内存模块。CRT库对这些模块来管理自己的
    注意到这些,除非有些地方有严重的错误(例如,

      在内存泄漏信息中有两种你从来没有见过的模块类型:                              
      空闲模块(free block)是一种被释放的内存模块                        
      Ignore block是你已经
    特殊标记过以至于在内存泄漏报
    告中不会出现的模块。

      设置CRT报告样式

      像以前的一样,按默认
    Debug窗格。你可以运用_Cr
    一个库,它可能重新设置输
    出位置回到输出窗口:
    方式,_CrtDumpMemoryLeaks倾
    tSetReportMode重新设置它到堆
    出到另一个位置。在这种情况下

    卸内存泄漏信息到输出窗口的
    存处,到另一个位置。如果你使用
    ,你能够利用下面的说明来设置输

      _CrtSetReportMode( _CRT_ERROR, _
    CRTDBG_MODE_DEBUG );
      关于使用_CrtSetRepor
    _CrtSetReportMode节。
    tMode去发送输出信息到另一个

    位置,要看Visual C++文件的


      在内存分配数目处设置一个断点                                                  
      在内存泄漏报告中的文件名和行号可
    里分配对于鉴定问题不总是充分的。在一
    次,但是它可能在某次调用中泄漏内存。
    配,还要知道泄漏发生的条件。对你来说
    显示的时候,文件名和行号之后,这是在
    ,"18"是内存分配号。它的意思是泄漏的
    告诉你泄漏的内存在那里被分配,但是了解内存在那
    个程序运行过程中,经常是一个分配将会被调用很多
    为了确定问题,你必须不但知道泄漏的内存在那里分
    ,使它成为可能的那条信息是内存分配号。当那些被
    curly brace中出现的数值。例如,在下面的输出中
    内存是你程序中内存分配的第十八个模块。
      Detected memory leaks!                                  
      Dumping objects ->

      C:PROGRAM FILESVISUAL STUDIOM
    normal block at
    yProjectsleaktestleaktest.cpp(20) : {18}

      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库计算在程序运行
    其它模块。因此带有分配号
    码分配的第n个对象。(在
    期间分配的所用内存模块,包括
    n的一个对象是在你的程序中分
    大部分情况下,它是不会的。)
    CRT自己分配的内存或者诸如MFC的
    配的第n个对象,但不可能是由代


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

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

      {,,msvcrtd.dll}_crtBreakAlloc                    

      现在,按RETURN。调试器评估调用并
    还没有设置任何断点,那么这个值是-1
    表中的值--例如,18 去中断早期在输出
    且把结果放置在Value栏。如果你在内存分配过程中
    。使用你想中断处内存分配的分配数值来代替Value
    过程中展现的分配。

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

      虽然在调试器中设置内
    码中设置它们。为了在你的
    内存分配):
    存分配断点通常更加容易,但是
    代码中设置一个内存分配断点,

    如果你喜欢的话,你可以在你的代
    可以增加这样一行(对于第十八个

      _crtBreakAlloc = 18;                                      

      最为一个选择,你可以使用有相同效果的_CrtSetBreakAlloc函数。  
      _CrtSetBreakAlloc(18);                                  

      比较内存状态

      定位内存泄漏的另一个
    个结构类型,_CrtMemState
    方法就是在关键点对应用程序的
    。你可以使用它来存储内存状态
    内存状态做快照。CRT库提供了一
    的一个快照。
      _CrtMemState s1, s2, s3;                              

      为了在特定点对内存状
    _CrtMemCheckpoint函数。
    态进行快照,可以传递一个_Crt
    此函数用当时内存状态的一个快
    MemState结构到he
    照来填充此结构:
      _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 ( _CrtMemDifferen
    ce( &s3, &s1, &s2) )
      _CrtMemDumpStatistics( &s3 );                    

      像名字暗示的一样,_C
    一个不同于这两个状态的结
    rtMemCheckpoint调用和使
    法。如果一个泄漏被检测到
    二元binary search techni
    rtMemDifference比较两个内存
    果(第三个参数)。在你的程序
    有_CrtMemDifference来比较结
    ,那么可以使用_CrtMemCheckpo
    que来定位泄漏。
    状态(最先的两个参数)并且产生
    开始和结尾处的_C
    果为检测内存泄漏提供了另一种方
    int调用来分割你的程序并且使用


    上一页 下一页




    map