Added an optional memory tracker (disabled by default) for detecting memory leaks and tracking allocations in the library.

This commit is contained in:
Joshua Jones 2010-03-09 04:40:27 +00:00
parent d5c5846d71
commit 849ba95609
5 changed files with 247 additions and 1 deletions

70
Headers/cMemoryTracker.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef CMEMORYTRACKER_H_INCLUDED
#define CMEMORYTRACKER_H_INCLUDED
#include "../include/cAudioDefines.h"
#ifdef CAUDIO_USE_MEMORYTRACKER
#include <map>
#include "../Headers/cMutex.h"
#include <iostream>
#include <fstream>
namespace cAudio
{
class cMemoryTracker
{
public:
cMemoryTracker();
~cMemoryTracker();
static cMemoryTracker* Instance()
{
static cMemoryTracker Singleton;
return &Singleton;
}
void AddAllocation(void* pointer, size_t size, const char* filename, int line, const char* function);
void RemoveAllocation(void* pointer);
private:
cAudioMutex Mutex;
struct cTrackedMemoryBlock
{
size_t size;
const char* filename;
int line;
const char* function;
};
std::map<void*, cTrackedMemoryBlock> TrackedBlocks;
#ifdef CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
struct Statistics
{
Statistics() : AllocationHighWaterMark(0), CurrentAllocationBytes(0),
TotalAllocationBytes(0), MaxNumAllocations(0),
CurrentNumAllocations(0), TotalNumAllocations(0)
{ }
size_t AllocationHighWaterMark;
size_t CurrentAllocationBytes;
size_t TotalAllocationBytes;
size_t MaxNumAllocations;
size_t CurrentNumAllocations;
size_t TotalNumAllocations;
} MemStats;
#endif
void DumpLeaks();
#ifdef CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
std::ofstream outMemLog;
#endif
};
};
#endif
#endif //! CMEMORYTRACKER_H_INCLUDED

116
Source/cMemoryTracker.cpp Normal file
View File

@ -0,0 +1,116 @@
#include "../Headers/cMemoryTracker.h"
#ifdef CAUDIO_USE_MEMORYTRACKER
namespace cAudio
{
cMemoryTracker::cMemoryTracker()
{
#ifdef CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
outMemLog.open("cAudioMemoryLog.log");
#endif
}
cMemoryTracker::~cMemoryTracker()
{
#ifdef CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
outMemLog.close();
#endif
DumpLeaks();
}
void cMemoryTracker::AddAllocation(void* pointer, size_t size, const char* filename, int line, const char* function)
{
cAudioMutexBasicLock lock(Mutex);
cTrackedMemoryBlock block;
block.size = size;
block.filename = filename;
block.line = line;
block.function = function;
TrackedBlocks[pointer] = block;
#ifdef CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
MemStats.CurrentAllocationBytes += size;
MemStats.TotalAllocationBytes += size;
MemStats.CurrentNumAllocations += 1;
MemStats.TotalNumAllocations += 1;
MemStats.AllocationHighWaterMark = MemStats.CurrentAllocationBytes > MemStats.AllocationHighWaterMark ? MemStats.CurrentAllocationBytes : MemStats.AllocationHighWaterMark;
MemStats.MaxNumAllocations = MemStats.CurrentNumAllocations > MemStats.MaxNumAllocations ? MemStats.CurrentNumAllocations : MemStats.MaxNumAllocations;
#endif
#ifdef CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
if(outMemLog.good())
{
outMemLog << "Allocation at " << pointer << " with size " << size << " bytes in " << filename << " (Line: " << line << ") function: " << function << std::endl;
outMemLog.flush();
}
#endif
}
void cMemoryTracker::RemoveAllocation(void* pointer)
{
cAudioMutexBasicLock lock(Mutex);
std::map<void*, cTrackedMemoryBlock>::iterator it = TrackedBlocks.find(pointer);
if(it != TrackedBlocks.end())
{
#ifdef CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
if(outMemLog.good())
{
outMemLog << "Deallocation of address " << pointer << " with size " << it->second.size << " bytes in " << it->second.filename << " (Line: " << it->second.line << ") function: " << it->second.function << std::endl;
outMemLog.flush();
}
#endif
#ifdef CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
size_t size = it->second.size;
MemStats.CurrentAllocationBytes -= size;
MemStats.CurrentNumAllocations -= 1;
#endif
TrackedBlocks.erase(pointer);
}
}
void cMemoryTracker::DumpLeaks()
{
cAudioMutexBasicLock lock(Mutex);
std::ofstream leakFile("cAudioMemoryLeaks.log");
#ifdef CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
//Dump Statistics
leakFile << "Highest Amount of Allocated Memory: " << MemStats.AllocationHighWaterMark << " bytes." << std::endl;
leakFile << "Memory Allocated at Shutdown: " << MemStats.CurrentAllocationBytes << " bytes." << std::endl;
leakFile << "Total Allocated Memory: " << MemStats.TotalAllocationBytes << " bytes." << std::endl;
leakFile << "Highest Number of Allocated Objects: " << MemStats.MaxNumAllocations << std::endl;
leakFile << "Objects Allocated at Shutdown: " << MemStats.CurrentNumAllocations << std::endl;
leakFile << "Total Objects Allocated: " << MemStats.TotalNumAllocations << std::endl;
leakFile << std::endl;
#endif
std::map<void*, cTrackedMemoryBlock>::iterator it;
for(it = TrackedBlocks.begin(); it != TrackedBlocks.end(); it++)
{
if(leakFile.good())
{
leakFile << "Address:" << it->first << " Size:" << it->second.size << " in " << it->second.filename << " (Line: " << it->second.line << ") function: " << it->second.function << std::endl;
leakFile.flush();
}
}
if(TrackedBlocks.size() == 0)
{
leakFile << "No Leaks Detected!" << std::endl;
leakFile.flush();
}
leakFile.close();
}
};
#endif

View File

@ -1,18 +1,34 @@
#include "../Headers/cStandardMemoryProvider.h"
#include "../Headers/cMemoryTracker.h"
#include <stdlib.h>
#include <limits>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
namespace cAudio
{
void* cStandardMemoryProvider::Allocate(size_t size, const char* filename, int line, const char* function)
{
return malloc(size);
void* ptr = malloc(size);
#ifdef CAUDIO_USE_MEMORYTRACKER
cMemoryTracker::Instance()->AddAllocation(ptr, size, filename, line, function);
#endif
return ptr;
}
void cStandardMemoryProvider::Free(void* pointer)
{
if(pointer)
{
#ifdef CAUDIO_USE_MEMORYTRACKER
cMemoryTracker::Instance()->RemoveAllocation(pointer);
#endif
free(pointer);
}
}

View File

@ -240,6 +240,10 @@
RelativePath=".\Headers\cMemorySource.h"
>
</File>
<File
RelativePath=".\Headers\cMemoryTracker.h"
>
</File>
<File
RelativePath=".\Headers\cMutex.h"
>
@ -352,6 +356,10 @@
RelativePath=".\Source\cMemorySource.cpp"
>
</File>
<File
RelativePath=".\Source\cMemoryTracker.cpp"
>
</File>
<File
RelativePath=".\Source\cMutex.cpp"
>

View File

@ -65,6 +65,15 @@
//! Tells cAudio to use the C standard memory functions for allocations (memalloc and free)
#define CAUDIO_MEMORY_USE_STD
//! Activates the internal memory tracker, which can be used to detect and locate memory leaks.
//#define CAUDIO_USE_MEMORYTRACKER
//! Tells the memory tracker to generate statistics on memory usage by cAudio
//#define CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
//! Tells the memory tracker to log each and every allocation done by cAudio. This can be very slow, use only if you are debugging an issue.
//#define CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
#endif //CAUDIO_PLATFORM_WIN
///////////////////////
@ -112,6 +121,15 @@
//! Tells cAudio to use the C standard memory functions for allocations (memalloc and free)
#define CAUDIO_MEMORY_USE_STD
//! Activates the internal memory tracker, which can be used to detect and locate memory leaks.
//#define CAUDIO_USE_MEMORYTRACKER
//! Tells the memory tracker to generate statistics on memory usage by cAudio
//#define CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
//! Tells the memory tracker to log each and every allocation done by cAudio. This can be very slow, use only if you are debugging an issue.
//#define CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
#endif //CAUDIO_PLATFORM_MAC
/////////////////////
@ -148,6 +166,15 @@
//! Tells cAudio to use the C standard memory functions for allocations (memalloc and free)
#define CAUDIO_MEMORY_USE_STD
//! Activates the internal memory tracker, which can be used to detect and locate memory leaks.
//#define CAUDIO_USE_MEMORYTRACKER
//! Tells the memory tracker to generate statistics on memory usage by cAudio
//#define CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
//! Tells the memory tracker to log each and every allocation done by cAudio. This can be very slow, use only if you are debugging an issue.
//#define CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
#endif //CAUDIO_PLATFORM_IPHONE
////////////////////
@ -198,6 +225,15 @@
//! Tells cAudio to use the C standard memory functions for allocations (memalloc and free)
#define CAUDIO_MEMORY_USE_STD
//! Activates the internal memory tracker, which can be used to detect and locate memory leaks.
//#define CAUDIO_USE_MEMORYTRACKER
//! Tells the memory tracker to generate statistics on memory usage by cAudio
//#define CAUDIO_MEMORYTRACKER_GENERATE_STATISTICS
//! Tells the memory tracker to log each and every allocation done by cAudio. This can be very slow, use only if you are debugging an issue.
//#define CAUDIO_MEMORYTRACKER_LOG_ALL_ALLOCATIONS
#endif //CAUDIO_PLATFORM_LINUX
#endif //CAUDIODEFINES_H