Last active
January 2, 2021 01:31
-
-
Save jeremy-rifkin/61439b360e92fd6e485488a081c86604 to your computer and use it in GitHub Desktop.
C++ utility for tracking memory allocations and identifying memory leaks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Include "memory_tracker.h" in every source file where you want to track allocations. | |
The memory tracker header should come after all other includes. | |
Include -DMEMORY_DEBUG in the build to enable memory tracking. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef MEMORY_DEBUG | |
#define __NO_REDEF_NEW // don't redefine new for the memory.cpp file - it'll obviously cause problems | |
#include "memory_tracker.h" | |
#include <assert.h> | |
#include <stdio.h> | |
#include <unordered_map> | |
// verbosity toggle | |
#if 1 | |
#define print_info(...) printf(__VA_ARGS__) | |
#else | |
#define print_info(...) ; | |
#endif | |
struct __alloc_t { | |
size_t size; | |
const char* file; | |
int line; | |
}; | |
// hash map for keeping track of transactions | |
static std::unordered_map<uint64_t, __alloc_t> __mem_allocations; | |
#define __contains(ptr) (__mem_allocations.bucket_count() > 0 && __mem_allocations.count((uint64_t)(ptr))) | |
void* __fn_new(size_t size, const char* file, int line) { | |
void* ptr = operator new(size); | |
print_info("allocating %3d bytes at %s:%d\n", size, file, line); | |
assert(!__contains((uint64_t)ptr)); | |
std::pair<uint64_t, __alloc_t> pair = std::pair<uint64_t, __alloc_t>((uint64_t)ptr, {size, file, line}); | |
__mem_allocations.insert(pair); | |
return ptr; | |
} | |
void __fn_delete(void* ptr) { | |
// if the ptr isn't in our map then we aren't responsible for tracking it | |
if(__contains((uint64_t)ptr)) { | |
size_t size = __mem_allocations.at((uint64_t)ptr).size; | |
(void)size; | |
print_info("deleting %lu bytes\n", (unsigned long)size); | |
__mem_allocations.erase((uint64_t)ptr); | |
free(ptr); | |
} | |
} | |
void* operator new(size_t size, const char* file, int line) { | |
return __fn_new(size, file, line); | |
} | |
void* operator new[](size_t size, const char* file, int line) { | |
return __fn_new(size, file, line); | |
} | |
void operator delete(void* ptr) { | |
__fn_delete(ptr); | |
} | |
void operator delete(void* ptr, size_t s) { | |
__fn_delete(ptr); | |
} | |
void operator delete[](void* ptr) { | |
__fn_delete(ptr); | |
} | |
void operator delete[](void* ptr, size_t s) { | |
__fn_delete(ptr); | |
} | |
int mem_total_alloc() { | |
int total = 0; | |
for(std::unordered_map<uint64_t, __alloc_t>::iterator it = __mem_allocations.begin(); it != __mem_allocations.end(); it++) { | |
total += it->second.size; | |
} | |
return total; | |
} | |
void mem_alloc_info() { | |
int alloc = mem_total_alloc(); | |
printf("-- total: %d bytes\n", alloc); | |
if(alloc > 0) | |
for(std::unordered_map<uint64_t, __alloc_t>::iterator it = __mem_allocations.begin(); it != __mem_allocations.end(); it++) { | |
printf(" > %3d bytes allocated on %s:%d\n", it->second.size, it->second.file, it->second.line); | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef MEMORY_DEBUG | |
#ifndef MEMORY_TRACKER_H | |
#define MEMORY_TRACKER_H | |
#include <new> | |
void* operator new(size_t, const char*, int); | |
void* operator new[](size_t, const char*, int); | |
void operator delete(void*); | |
void operator delete(void*, size_t); | |
void operator delete[](void*); | |
void operator delete[](void*, size_t); | |
int mem_total_alloc(); | |
void mem_alloc_info(); | |
#ifndef __NO_REDEF_NEW | |
#define new new(__FILE__, __LINE__) | |
#endif | |
#endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment