| 1 | #ifdef DEBUG_MEMORY_LEAK |
|---|
| 2 | |
|---|
| 3 | #include "Common/include/Message.h" |
|---|
| 4 | #include <cstdio> |
|---|
| 5 | #include <cstdlib> |
|---|
| 6 | #include <cassert> |
|---|
| 7 | #include <cstddef> |
|---|
| 8 | #include <map> |
|---|
| 9 | |
|---|
| 10 | using namespace std; |
|---|
| 11 | using namespace morpheo; |
|---|
| 12 | |
|---|
| 13 | #undef new |
|---|
| 14 | |
|---|
| 15 | // Global flags set by macros in MemCheck.h |
|---|
| 16 | bool traceFlag = false; |
|---|
| 17 | bool activeFlag = false; |
|---|
| 18 | |
|---|
| 19 | namespace { |
|---|
| 20 | |
|---|
| 21 | // Memory map entry type |
|---|
| 22 | struct Info |
|---|
| 23 | { |
|---|
| 24 | // void* ptr; |
|---|
| 25 | const char* file; |
|---|
| 26 | long line; |
|---|
| 27 | size_t size; |
|---|
| 28 | }; |
|---|
| 29 | |
|---|
| 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; |
|---|
| 38 | |
|---|
| 39 | memMap_t memMap; |
|---|
| 40 | |
|---|
| 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); |
|---|
| 50 | |
|---|
| 51 | assert(it != memMap.end()); |
|---|
| 52 | |
|---|
| 53 | // Remove pointer from map |
|---|
| 54 | memMap.erase(it); |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 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); |
|---|
| 81 | |
|---|
| 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 | |
|---|
| 105 | } // End anonymous namespace |
|---|
| 106 | |
|---|
| 107 | // Overload scalar new |
|---|
| 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; |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | // Overload array new |
|---|
| 131 | void* operator new[](size_t size, const char* file, long line) |
|---|
| 132 | { |
|---|
| 133 | return operator new(size, file, line); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | // Override scalar delete |
|---|
| 137 | void operator delete(void* p) |
|---|
| 138 | { |
|---|
| 139 | bool can_free = true; |
|---|
| 140 | |
|---|
| 141 | if (activeFlag) |
|---|
| 142 | { |
|---|
| 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 |
|---|
| 154 | |
|---|
| 155 | can_free = false; |
|---|
| 156 | msgError("Attempt to delete unknown pointer: %p\n", p); |
|---|
| 157 | } |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | if (can_free) |
|---|
| 162 | { |
|---|
| 163 | if(traceFlag) |
|---|
| 164 | msgInformation("Deleted memory at address %p\n", p); |
|---|
| 165 | |
|---|
| 166 | free(p); |
|---|
| 167 | } |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | // Override array delete |
|---|
| 171 | void operator delete[](void* p) |
|---|
| 172 | { |
|---|
| 173 | operator delete(p); |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | #endif // DEBUG_MEMORY_LEAK |
|---|