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