[112] | 1 | #ifdef DEBUG_MEMORY_LEAK |
---|
| 2 | |
---|
| 3 | #include <cstdio> |
---|
| 4 | #include <cstdlib> |
---|
| 5 | #include <cassert> |
---|
| 6 | #include <cstddef> |
---|
| 7 | using namespace std; |
---|
| 8 | #undef new |
---|
| 9 | |
---|
| 10 | // Global flags set by macros in MemCheck.h |
---|
| 11 | bool traceFlag = false; |
---|
| 12 | bool activeFlag = true; |
---|
| 13 | |
---|
| 14 | namespace { |
---|
| 15 | |
---|
| 16 | // Memory map entry type |
---|
| 17 | struct Info { |
---|
| 18 | void* ptr; |
---|
| 19 | const char* file; |
---|
| 20 | long line; |
---|
| 21 | }; |
---|
| 22 | |
---|
| 23 | // Memory map data |
---|
| 24 | const size_t MAXPTRS = 10000u; |
---|
| 25 | Info memMap[MAXPTRS]; |
---|
| 26 | size_t nptrs = 0; |
---|
| 27 | |
---|
| 28 | // Searches the map for an address |
---|
| 29 | int findPtr(void* p) { |
---|
| 30 | for(size_t i = 0; i < nptrs; ++i) |
---|
| 31 | if(memMap[i].ptr == p) |
---|
| 32 | return i; |
---|
| 33 | return -1; |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | void delPtr(void* p) { |
---|
| 37 | int pos = findPtr(p); |
---|
| 38 | assert(pos >= 0); |
---|
| 39 | // Remove pointer from map |
---|
| 40 | for(size_t i = pos; i < nptrs-1; ++i) |
---|
| 41 | memMap[i] = memMap[i+1]; |
---|
| 42 | --nptrs; |
---|
| 43 | } |
---|
| 44 | |
---|
| 45 | // Dummy type for static destructor |
---|
| 46 | struct Sentinel { |
---|
| 47 | ~Sentinel() { |
---|
| 48 | if(nptrs > 0) { |
---|
| 49 | printf("Leaked memory at:\n"); |
---|
| 50 | for(size_t i = 0; i < nptrs; ++i) |
---|
| 51 | printf("\t%p (file: %s, line %ld)\n", |
---|
| 52 | memMap[i].ptr, memMap[i].file, memMap[i].line); |
---|
| 53 | } |
---|
| 54 | else |
---|
| 55 | printf("No user memory leaks!\n"); |
---|
| 56 | } |
---|
| 57 | }; |
---|
| 58 | |
---|
| 59 | // Static dummy object |
---|
| 60 | Sentinel s; |
---|
| 61 | |
---|
| 62 | } // End anonymous namespace |
---|
| 63 | |
---|
| 64 | // Overload scalar new |
---|
| 65 | void* operator new(size_t siz, const char* file, long line) { |
---|
| 66 | void* p = malloc(siz); |
---|
| 67 | if(activeFlag) { |
---|
| 68 | if(nptrs == MAXPTRS) { |
---|
| 69 | printf("memory map too small (increase MAXPTRS)\n"); |
---|
| 70 | exit(1); |
---|
| 71 | } |
---|
| 72 | memMap[nptrs].ptr = p; |
---|
| 73 | memMap[nptrs].file = file; |
---|
| 74 | memMap[nptrs].line = line; |
---|
| 75 | ++nptrs; |
---|
| 76 | } |
---|
| 77 | if(traceFlag) { |
---|
| 78 | printf("Allocated %u bytes at address %p ", siz, p); |
---|
| 79 | printf("(file: %s, line: %ld)\n", file, line); |
---|
| 80 | } |
---|
| 81 | return p; |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | // Overload array new |
---|
| 85 | void* operator new[](size_t siz, const char* file, long line) { |
---|
| 86 | return operator new(siz, file, line); |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | // Override scalar delete |
---|
| 90 | void operator delete(void* p) { |
---|
| 91 | if(findPtr(p) >= 0) { |
---|
| 92 | free(p); |
---|
| 93 | assert(nptrs > 0); |
---|
| 94 | delPtr(p); |
---|
| 95 | if(traceFlag) |
---|
| 96 | printf("Deleted memory at address %p\n", p); |
---|
| 97 | } |
---|
| 98 | else if(!p && activeFlag) |
---|
| 99 | printf("Attempt to delete unknown pointer: %p\n", p); |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | // Override array delete |
---|
| 103 | void operator delete[](void* p) { |
---|
| 104 | operator delete(p); |
---|
| 105 | } |
---|
| 106 | #endif // DEBUG_MEMORY_LEAK |
---|