HLLib/HLLib/DebugMemory.cpp

178 lines
4.0 KiB
C++

/*
* HLLib
* Copyright (C) 2006-2010 Ryan Gregg
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later
* version.
*/
#include "DebugMemory.h"
#if DEBUG_TRACK_MEMORY
#define DEBUG_TRACK_MEMORY_HASH 4 // Number of hashmap buckets. (2^Value)
#define DEBUG_TRACK_MEMORY_ALIGNMENT 4 // Number of least significant bits to ignore in hash. (For memory alignment.)
#ifdef _WIN32
# define DEBUG_TRACK_DUMP_FILE "C:\\dump.txt" // File to dump memory dump to.
#else
# define DEBUG_TRACK_DUMP_FILE "/var/tmp/dump.txt" // File to dump memory dump to.
#endif
struct SAllocInfo
{
void *pAddress;
size_t uiSize;
char lpFile[64];
unsigned int uiLine;
SAllocInfo *pNext;
};
struct SAllocList
{
SAllocList() : uiCount(0), pFirst(0)
{
}
unsigned int uiCount;
SAllocInfo *pFirst;
};
bool bTrackMemory = false;
unsigned int uiTotalTracks = 0;
unsigned int uiPeakTracks = 0;
size_t uiTotalBytes = 0;
size_t uiPeakBytes = 0;
SAllocList lpAllocList[1 << DEBUG_TRACK_MEMORY_HASH];
// Disable void* to unsigned long cast warning.
#pragma warning(disable: 4311)
void StartTracking()
{
bTrackMemory = true;
}
void StopTracking()
{
bTrackMemory = false;
}
void AddTrack(void *pAddress, size_t uiSize, const char *lpFile, unsigned int uiLine)
{
if(!bTrackMemory)
{
return;
}
SAllocInfo *pAllocInfo = (SAllocInfo *)malloc(sizeof(SAllocInfo));
pAllocInfo->pAddress = pAddress;
strncpy(pAllocInfo->lpFile, lpFile, sizeof(pAllocInfo->lpFile));
pAllocInfo->lpFile[sizeof(pAllocInfo->lpFile) - 1] = '\0';
pAllocInfo->uiLine = uiLine;
pAllocInfo->uiSize = uiSize;
SAllocList *pAllocList = &lpAllocList[((unsigned long)pAddress >> DEBUG_TRACK_MEMORY_ALIGNMENT) & ((unsigned long)~0 >> (32 - DEBUG_TRACK_MEMORY_HASH))];
pAllocInfo->pNext = pAllocList->pFirst;
pAllocList->pFirst = pAllocInfo;
pAllocList->uiCount++;
uiTotalTracks++;
if(uiTotalTracks > uiPeakTracks)
{
uiPeakTracks = uiTotalTracks;
}
uiTotalBytes += uiSize;
if(uiTotalBytes > uiPeakBytes)
{
uiPeakBytes = uiTotalBytes;
}
}
void RemoveTrack(void *pAddress)
{
SAllocList *pAllocList = &lpAllocList[((unsigned long)pAddress >> DEBUG_TRACK_MEMORY_ALIGNMENT) & ((unsigned long)~0 >> (32 - DEBUG_TRACK_MEMORY_HASH))];
if(pAllocList->pFirst == 0)
{
return;
}
SAllocInfo *pLast, *pCurrent = pAllocList->pFirst;
if(pCurrent->pAddress == pAddress)
{
pAllocList->uiCount--;
uiTotalTracks--;
uiTotalBytes -= pCurrent->uiSize;
pAllocList->pFirst = pCurrent->pNext;
free(pCurrent);
return;
}
pLast = pCurrent;
pCurrent = pCurrent->pNext;
while(pCurrent)
{
if(pCurrent->pAddress == pAddress)
{
pAllocList->uiCount--;
uiTotalTracks--;
uiTotalBytes -= pCurrent->uiSize;
pLast->pNext = pCurrent->pNext;
free(pCurrent);
return;
}
pLast = pCurrent;
pCurrent = pCurrent->pNext;
}
}
void DumpTracks()
{
FILE *pFile = fopen(DEBUG_TRACK_DUMP_FILE, "wt");
if(pFile == 0)
return;
for(unsigned int i = 0; i < (1 << DEBUG_TRACK_MEMORY_HASH); i++)
{
if(lpAllocList[i].uiCount > 0)
{
fprintf(pFile, "List: %u (%u entries)\n", i, lpAllocList[i].uiCount);
SAllocInfo *pCurrent = lpAllocList[i].pFirst;
while(pCurrent)
{
fprintf(pFile, "Address: 0x%.8x %-8.u bytes at %s (%u)\n", (unsigned long)pCurrent->pAddress, pCurrent->uiSize, pCurrent->lpFile, pCurrent->uiLine);
pCurrent = pCurrent->pNext;
}
fprintf(pFile, "\n");
}
}
fprintf(pFile, "Peak: %u B (%.2f KB) and %u allocations.\n", uiPeakBytes, (double)uiPeakBytes / 1024.0, uiPeakTracks);
fprintf(pFile, "Total: %u B (%.2f KB) in %u allocations.\n", uiTotalBytes, (double)uiTotalBytes / 1024.0, uiTotalTracks);
fclose(pFile);
}
#pragma warning(default: 4311)
#endif