Входя в _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