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 = false; |
---|
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 |
---|