Skip to content

Instantly share code, notes, and snippets.

@jeremy-rifkin
Last active January 2, 2021 01:31
Show Gist options
  • Save jeremy-rifkin/61439b360e92fd6e485488a081c86604 to your computer and use it in GitHub Desktop.
Save jeremy-rifkin/61439b360e92fd6e485488a081c86604 to your computer and use it in GitHub Desktop.
C++ utility for tracking memory allocations and identifying memory leaks
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.
#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
#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