[112] | 1 | #ifdef DEBUG_MEMORY_LEAK |
---|
| 2 | |
---|
[115] | 3 | #include "Common/include/Message.h" |
---|
[112] | 4 | #include <cstdio> |
---|
| 5 | #include <cstdlib> |
---|
| 6 | #include <cassert> |
---|
| 7 | #include <cstddef> |
---|
[115] | 8 | #include <map> |
---|
| 9 | |
---|
[112] | 10 | using namespace std; |
---|
[115] | 11 | using namespace morpheo; |
---|
| 12 | |
---|
[112] | 13 | #undef new |
---|
| 14 | |
---|
| 15 | // Global flags set by macros in MemCheck.h |
---|
[117] | 16 | bool traceFlag = false; |
---|
[113] | 17 | bool activeFlag = false; |
---|
[112] | 18 | |
---|
| 19 | namespace { |
---|
| 20 | |
---|
[115] | 21 | // Memory map entry type |
---|
| 22 | struct Info |
---|
| 23 | { |
---|
| 24 | // void* ptr; |
---|
| 25 | const char* file; |
---|
| 26 | long line; |
---|
| 27 | size_t size; |
---|
| 28 | }; |
---|
[112] | 29 | |
---|
[115] | 30 | bool Info_lt(std::pair<void *,Info> a, std::pair<void *,Info> b) |
---|
| 31 | { |
---|
| 32 | return a.second.size < b.second.size; |
---|
| 33 | } |
---|
| 34 | |
---|
| 35 | // Memory map data |
---|
| 36 | typedef map<void *,Info> memMap_t; |
---|
| 37 | typedef map<void *,Info>::iterator memMap_it; |
---|
[112] | 38 | |
---|
[115] | 39 | memMap_t memMap; |
---|
[112] | 40 | |
---|
[115] | 41 | // Searches the map for an address |
---|
| 42 | memMap_it findPtr(void* p) |
---|
| 43 | { |
---|
| 44 | return memMap.find(p); |
---|
| 45 | } |
---|
| 46 | |
---|
| 47 | void delPtr(void* p) |
---|
| 48 | { |
---|
| 49 | memMap_it it = findPtr(p); |
---|
[112] | 50 | |
---|
[115] | 51 | assert(it != memMap.end()); |
---|
| 52 | |
---|
| 53 | // Remove pointer from map |
---|
| 54 | memMap.erase(it); |
---|
| 55 | } |
---|
[112] | 56 | |
---|
[115] | 57 | // Dummy type for static destructor |
---|
| 58 | struct Sentinel |
---|
| 59 | { |
---|
| 60 | ~Sentinel() |
---|
| 61 | { |
---|
| 62 | size_t size = memMap.size(); |
---|
| 63 | if(size > 0) |
---|
| 64 | { |
---|
| 65 | size_t size_sum = 0; |
---|
| 66 | msgWarning("Leaked memory at:\n"); |
---|
| 67 | for (memMap_it it=memMap.begin(); |
---|
| 68 | it!=memMap.end(); |
---|
| 69 | ++it) |
---|
| 70 | { |
---|
| 71 | size_t s = it->second.size; |
---|
| 72 | size_sum += s; |
---|
| 73 | |
---|
| 74 | msgWarning("\t%p : %u bytes (file: %s, line %ld)\n", |
---|
| 75 | it->first, |
---|
| 76 | s, |
---|
| 77 | it->second.file, |
---|
| 78 | it->second.line); |
---|
| 79 | } |
---|
| 80 | msgWarning("Total : %u bytes on %d localisations\n",size_sum, size); |
---|
[112] | 81 | |
---|
[115] | 82 | uint32_t nb_top = (size>10)?10:size; |
---|
| 83 | msgWarning("Top %d of leaked memory\n",nb_top); |
---|
| 84 | for (uint32_t i=0; i<nb_top; ++i) |
---|
| 85 | { |
---|
| 86 | memMap_it max = max_element(memMap.begin(), memMap.end(),Info_lt); |
---|
| 87 | |
---|
| 88 | msgWarning(" * [%d] %u bytes (file: %s, line %ld)\n", |
---|
| 89 | i, |
---|
| 90 | max->second.size, |
---|
| 91 | max->second.file, |
---|
| 92 | max->second.line); |
---|
| 93 | |
---|
| 94 | memMap.erase(max); |
---|
| 95 | } |
---|
| 96 | } |
---|
| 97 | else |
---|
| 98 | msgInformation("No user memory leaks!\n"); |
---|
| 99 | } |
---|
| 100 | }; |
---|
| 101 | |
---|
| 102 | // Static dummy object |
---|
| 103 | Sentinel s; |
---|
| 104 | |
---|
[112] | 105 | } // End anonymous namespace |
---|
| 106 | |
---|
| 107 | // Overload scalar new |
---|
[115] | 108 | void* operator new(size_t size, const char* file, long line) |
---|
| 109 | { |
---|
| 110 | void* p = malloc(size); |
---|
| 111 | |
---|
| 112 | if(activeFlag) |
---|
| 113 | { |
---|
| 114 | Info info; |
---|
| 115 | info.file = file; |
---|
| 116 | info.line = line; |
---|
| 117 | info.size = size; |
---|
| 118 | |
---|
| 119 | memMap[p] = info; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | if(traceFlag) |
---|
| 123 | { |
---|
| 124 | msgInformation("Allocated %u bytes at address %p (file: %s, line: %ld)\n", size, p, file, line); |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | return p; |
---|
[112] | 128 | } |
---|
| 129 | |
---|
| 130 | // Overload array new |
---|
[115] | 131 | void* operator new[](size_t size, const char* file, long line) |
---|
| 132 | { |
---|
| 133 | return operator new(size, file, line); |
---|
[112] | 134 | } |
---|
| 135 | |
---|
| 136 | // Override scalar delete |
---|
[115] | 137 | void operator delete(void* p) |
---|
| 138 | { |
---|
[117] | 139 | bool can_free = true; |
---|
[115] | 140 | |
---|
[117] | 141 | if (activeFlag) |
---|
[115] | 142 | { |
---|
[117] | 143 | memMap_it it = findPtr(p); |
---|
| 144 | |
---|
| 145 | if (it != memMap.end()) |
---|
| 146 | { |
---|
| 147 | // this pointer is previously allocated |
---|
| 148 | delPtr(p); |
---|
| 149 | |
---|
| 150 | } |
---|
| 151 | else |
---|
| 152 | { |
---|
| 153 | // this pointer is not previously allocated |
---|
[115] | 154 | |
---|
[117] | 155 | can_free = false; |
---|
| 156 | msgError("Attempt to delete unknown pointer: %p\n", p); |
---|
| 157 | } |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | |
---|
| 161 | if (can_free) |
---|
| 162 | { |
---|
[115] | 163 | if(traceFlag) |
---|
[117] | 164 | msgInformation("Deleted memory at address %p\n", p); |
---|
| 165 | |
---|
| 166 | free(p); |
---|
[115] | 167 | } |
---|
[112] | 168 | } |
---|
| 169 | |
---|
| 170 | // Override array delete |
---|
[115] | 171 | void operator delete[](void* p) |
---|
| 172 | { |
---|
| 173 | operator delete(p); |
---|
[112] | 174 | } |
---|
[115] | 175 | |
---|
[112] | 176 | #endif // DEBUG_MEMORY_LEAK |
---|