0 /* See LICENSE file for copyright and license details. */
1 #ifdef MEM_CHECK
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <termbox.h>
7 #define allocation (__allocation)
8 #define allocationCount (__allocationCount)
9 #define output (__output)
10 #define PATH "mem.log"
11
12 void __free(void*, const char*, int, const char*);
13 void* __malloc(size_t, const char*, int, const char*);
14 void* __calloc(size_t, size_t, const char*, int, const char*);
15 void* __realloc(void*, size_t, const char*, int, const char*);
16 void __init();
17 void __check();
18 int __main(int argc, char* argv[]);
19
20 struct __allocation {
21 void* ptr;
22 int line;
23 size_t size;
24 const char* file;
25 const char* func;
26 };
27
28 int main(int argc, char* argv[]) {
29 __init();
30 int ret = __main(argc, argv);
31 __check();
32 return ret;
33 }
34
35 struct __allocation* __allocation;
36 uint64_t __allocationCount;
37 FILE* __output = NULL;
38 int __warnings = 0;
39
40 void __debug(const char* out) {
41 fprintf(output, out);
42 fflush(output);
43 }
44
45 void __init() {
46 allocation=NULL;
47 allocationCount=0;
48 output = fopen(PATH,"wb");
49 }
50
51 void __free(void* ptr, const char* file, int line, const char* func) {
52 uint32_t i=0;
53 if(ptr) {
54 while(i!=allocationCount && ptr!=allocation[i].ptr) i++;
55 if(i==allocationCount) {
56 fprintf(output,
57 "(WARNING Freeing non-allocated memory) " \
58 "free : %p, %s, Line %d : %s\n",
59 ptr, file, line, func);
60 fflush(output);
61 #ifndef EXIT_ON_ERROR
62 __warnings++;
63 return;
64 #else
65 fclose(output);
66 tb_shutdown();
67 printf("mem_check detected a fatal error\n");
68 return exit(0);
69 #endif
70 }
71 for(uint32_t j=i; j!=allocationCount-1; j++)
72 allocation[j] = allocation[j+1];
73 allocationCount--;
74 allocation = realloc(allocation,
75 sizeof(struct __allocation) *
76 allocationCount);
77 }
78 if(i>allocationCount)
79 fprintf(output, "Error free : %p | %s, Line %d : %s\n",
80 ptr, file, line, func);
81 else
82 fprintf(output, "Free : %p | %s, Line %d : %s\n",
83 ptr, file, line, func);
84 fflush(output);
85 free(ptr);
86 }
87
88 void* __malloc(size_t size, const char* file, int line, const char* func) {
89 void* ptr = malloc(size);
90 if(ptr) {
91 allocationCount++;
92 allocation = realloc(allocation,
93 sizeof(struct __allocation) *
94 allocationCount);
95 allocation[allocationCount-1].ptr = ptr;
96 allocation[allocationCount-1].line = line;
97 allocation[allocationCount-1].size = size;
98 allocation[allocationCount-1].file = file;
99 allocation[allocationCount-1].func = func;
100 }
101 fprintf(output, "malloc : %p, size : %ld | %s, Line %d : %s\n",
102 ptr, size, file, line, func);
103 fflush(output);
104 return ptr;
105 }
106
107 void* __calloc(size_t num, size_t size, const char* file,
108 int line, const char* func) {
109 void* ptr = calloc(num, size);
110 if(ptr) {
111 allocationCount++;
112 allocation = realloc(allocation,
113 sizeof(struct __allocation) *
114 allocationCount);
115 allocation[allocationCount-1].ptr = ptr;
116 allocation[allocationCount-1].line = line;
117 allocation[allocationCount-1].size = size;
118 allocation[allocationCount-1].file = file;
119 allocation[allocationCount-1].func = func;
120 }
121 fprintf(output, "calloc : %p, size : %ld | %s, Line %d : %s\n",
122 ptr, size, file, line, func);
123 fflush(output);
124 return ptr;
125 }
126
127 void* __realloc(void* ptr, size_t size, const char* file,
128 int line, const char* func) {
129 if (ptr==NULL) return __malloc(size, file, line, func);
130 void* _ptr = realloc(ptr, size);
131 if(_ptr != ptr) {
132 uint32_t i=0;
133 for(i=0; i!=allocationCount && ptr != allocation[i].ptr; i++) ;
134 if(allocationCount>i) {
135 allocation[i].ptr = _ptr;
136 allocation[i].line = line;
137 allocation[i].size = size;
138 allocation[i].file = file;
139 allocation[i].func = func;
140 }
141 }
142 fprintf(output, "realloc : %p, size : %ld | %s, Line %d : %s\n",
143 _ptr, size, file, line, func);
144 fflush(output);
145 return _ptr;
146 }
147
148 void __check() {
149 fprintf(output, "-----------------------\n");
150 if (allocationCount == 0)
151 fprintf(output, "No memory leak detected\n");
152 else {
153 fprintf(output, "%ld memory leaks detected\n",
154 allocationCount);
155 printf("WARNING: Memory leaks detected (%ld)\n",
156 allocationCount);
157 }
158 if (__warnings) {
159 fprintf(output, "%d invalid memory operations detected\n",
160 __warnings);
161 printf("WARNING: %d invalid memory operations detected\n",
162 __warnings);
163 }
164 for(uint32_t i=0; i!=allocationCount; i++)
165 fprintf(output, "Leak : %p, size : %ld | %s, Line %d : %s\n",
166 allocation[i].ptr,
167 allocation[i].size,
168 allocation[i].file,
169 allocation[i].line,
170 allocation[i].func);
171 fclose(output);
172 }
173 #else
174 typedef int remove_iso_warning;
175 #endif
176