【问题标题】:show location of biggest memory leak on Windows显示 Windows 上最大内存泄漏的位置
【发布时间】:2016-05-23 04:42:50
【问题描述】:

我的程序有很大的漏洞。我通过将它放在我的stdafx.h 中来使用调试堆:

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

然后我通过在退出前添加这段代码来捕获文本文件中的所有泄漏:

HANDLE hLogFile;
hLogFile = CreateFile( "T:\\MyProject\\heap.txt", GENERIC_WRITE, 
                       FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 
                       FILE_ATTRIBUTE_NORMAL, NULL);
 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
 _CrtSetReportFile(_CRT_WARN, hLogFile);

_CrtDumpMemoryLeaks();

exit( EXIT_SUCCESS );

然而,即使这样,数据也是一个接一个地泄漏,这是太低级的信息。

【问题讨论】:

    标签: windows visual-studio debugging memory-leaks heap-memory


    【解决方案1】:

    步入_CrtDumpMemoryLeaks(),代码其实很容易理解。我编写了自己的函数来汇总数据,报告每行代码泄漏的字节数并按泄漏大小排序。

    但是,它需要 dbgheap.c 中的静态变量才能工作。我试图制作一个没有这些静态符号的dbgheap.c 版本,并试图从中制作一个迷你 DLL(但它抱怨我在 MSFT 代码中的任何地方都找不到丢失的符号,_heap_regions)。相反,我决定将这段代码放在上面调用_CrtDumpMemoryLeaks()的代码之前:

    // Put a breakpoint here; step INTO the malloc, then in variable watch
    // window evaluate: _CrtDumpMemoryLeakSummary( _pFirstBlock );
    void* pvAccess = malloc(1);
    

    这又是 _CrtDumpMemoryLeakSummary 函数的代码:

        #define _CRTBLD
        #include "C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\dbgint.h"
    
        typedef struct {
            const char* pszFileName;
            int         iLine;
            int         iTotal;
        } Location_T;
    
        #define MAX_SUMMARY 5000
        static Location_T aloc[ MAX_SUMMARY ];
    
    
    
        static int CompareFn( const void* pv1, const void* pv2 ) {
          Location_T* ploc1 = (Location_T*) pv1;
          Location_T* ploc2 = (Location_T*) pv2;
    
          if ( ploc1->iTotal > ploc2->iTotal )
              return -1;
          if ( ploc1->iTotal < ploc2->iTotal )
              return 1;
          return 0;
        }
    
    
    
        void _CrtDumpMemoryLeakSummary( _CrtMemBlockHeader* pHead )
        {
              int iLocUsed = 0, iUnbucketed = 0, i;
    
              for ( /*pHead = _pFirstBlock */;
                    pHead != NULL && /* pHead != _pLastBlock && */ iLocUsed < MAX_SUMMARY;
                    pHead = pHead->pBlockHeaderNext ) {
    
                   const char* pszFileName = pHead->szFileName ? pHead->szFileName : "<UNKNOWN>";
    
                   // Linear search is theoretically horribly slow but saves trouble of
                   // avoiding heap use while measuring heap use.
                   int i;
                   for ( i = 0; i < iLocUsed; i++ ) {
    
                       // To speed search, compare line number (fast) before strcmp() (slow).
                       // If szFileName were guaranteed to be __LINE__ then we could take advantage
                       // of __LINE__ always having the same address for any given file, and just
                       // compare pointers rather than using strcmp().  However, szFileName could
                       // be something else.
    
                       if ( pHead->nLine == aloc[i].iLine &&
                            strcmp( pszFileName, aloc[i].pszFileName ) == 0 ) {
                           aloc[i].iTotal += pHead->nDataSize;
                           break;
                       }
                   }
    
                   if ( i == iLocUsed ) {
                       aloc[i].pszFileName = pszFileName;
                       aloc[i].iLine       = pHead->nLine;
                       aloc[i].iTotal      = pHead->nDataSize;
                       iLocUsed++;
                   }             
              }
    
              if ( iLocUsed == MAX_SUMMARY )
                  _RPT0( _CRT_WARN, "\n\n\nARNING: RAN OUT OF BUCKETS! DATA INCOMPLETE!!!\n\n\n" );
    
              qsort( aloc, iLocUsed, sizeof( Location_T ), CompareFn );
    
              _RPT0(_CRT_WARN, "SUMMARY OF LEAKS\n" );
              _RPT0(_CRT_WARN, "\n" );
              _RPT0(_CRT_WARN, "bytes leaked  code location\n" );
              _RPT0(_CRT_WARN, "------------  -------------\n" );
    
              for ( i = 0; i < iLocUsed; i++ )
                  _RPT3(_CRT_WARN, "%12d  %s:%d\n", aloc[i].iTotal, aloc[i].pszFileName, aloc[i].iLine );
        }
    

    它产生这样的输出:

    SUMMARY OF LEAKS
    
    bytes leaked  code location
    ------------  -------------
          912997  <UNKNOWN>:0
          377800  ..\MyProject\foo.h:205
          358400  ..\MyProject\A.cpp:959
          333672  ..\MyProject\B.cpp:359
            8192  f:\dd\vctools\crt_bld\self_x86\crt\src\_getbuf.c:58
            6144  ..\MyProject\Interpreter.cpp:196
            4608  ..\MyProject\Interpreter.cpp:254
            3634  f:\dd\vctools\crt_bld\self_x86\crt\src\stdenvp.c:126
            2960  ..\MyProject\C.cpp:947
            2089  ..\MyProject\D.cpp:1031
            2048  f:\dd\vctools\crt_bld\self_x86\crt\src\ioinit.c:136
            2048  f:\dd\vctools\crt_bld\self_x86\crt\src\_file.c:133
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 2014-05-03
      • 2019-07-17
      • 2016-01-29
      • 1970-01-01
      相关资源
      最近更新 更多