Mercurial > hg > early-roguelike
comparison urogue/memory.c @ 288:b8919055c2fc
UltraRogue: compile out the built-in memory checking.
Functions in memory.c tracked and instrumented memory allocation. This
mechanism logged information to a text file and also added a 16KB guard
area to every allocation. Neither of these are desirable in a multi-
user environment, so the whole memory tracking subsystem has been
disabled.
The behavior can be enabled with a configure flag, but it would be a
better idea to use Valgrind to deal with memory bugs.
author | John "Elwin" Edwards |
---|---|
date | Fri, 24 Nov 2017 13:22:26 -0500 |
parents | c4b12d2d1dcd |
children | e52a8a7ad4c5 |
comparison
equal
deleted
inserted
replaced
287:0b3d1b38998f | 288:b8919055c2fc |
---|---|
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 | 13 |
14 #include "dict.h" | 14 #include "dict.h" |
15 #include "memory.h" | 15 #include "memory.h" |
16 #include "rogue.h" | 16 #include "rogue.h" |
17 | |
18 #ifdef HAVE_CONFIG_H | |
19 #include "config.h" | |
20 #endif | |
17 | 21 |
18 static char sccsid[] = "%W%\t%G%"; | 22 static char sccsid[] = "%W%\t%G%"; |
19 | 23 |
20 /* Debugging memory allocation code that tries to trap common memory problems | 24 /* Debugging memory allocation code that tries to trap common memory problems |
21 like overwriting storage and stepping on memory pointer chains. If code | 25 like overwriting storage and stepping on memory pointer chains. If code |
38 /* set the debug level */ | 42 /* set the debug level */ |
39 void mem_debug(const int level) | 43 void mem_debug(const int level) |
40 { | 44 { |
41 memdebug_level = level; | 45 memdebug_level = level; |
42 | 46 |
47 #ifdef MEM_DEBUG | |
43 if (trace_file == NULL) | 48 if (trace_file == NULL) |
44 trace_file = fopen("trace", "w"); | 49 trace_file = fopen("trace", "w"); |
45 | 50 |
46 /* all except 0, 1, and unknown fall through */ | 51 /* all except 0, 1, and unknown fall through */ |
47 switch(memdebug_level) { | 52 switch(memdebug_level) { |
57 fprintf(trace_file, "!!! Unknown memory debug level set, enabling level 1, "); | 62 fprintf(trace_file, "!!! Unknown memory debug level set, enabling level 1, "); |
58 memdebug_level = 1; | 63 memdebug_level = 1; |
59 break; | 64 break; |
60 } | 65 } |
61 fprintf(trace_file, "fence size = %d\n", FENCE_SIZE); | 66 fprintf(trace_file, "fence size = %d\n", FENCE_SIZE); |
67 #endif | |
62 } | 68 } |
63 | 69 |
64 /* set memory tracking on or off */ | 70 /* set memory tracking on or off */ |
65 /* turning it off deletes all tracking data */ | 71 /* turning it off deletes all tracking data */ |
66 void mem_tracking(int flag) | 72 void mem_tracking(int flag) |
67 { | 73 { |
74 #ifdef MEM_DEBUG | |
68 /* do nothing if debuglevel is too low */ | 75 /* do nothing if debuglevel is too low */ |
69 if (memdebug_level < 2) | 76 if (memdebug_level < 2) |
70 return; | 77 return; |
71 | 78 |
72 /* turn on tracking */ | 79 /* turn on tracking */ |
84 /* turn off tracking */ | 91 /* turn off tracking */ |
85 else if (allocations != NULL) { | 92 else if (allocations != NULL) { |
86 dict_destroy(allocations); | 93 dict_destroy(allocations); |
87 allocations = NULL; | 94 allocations = NULL; |
88 } | 95 } |
96 #endif | |
89 } | 97 } |
90 | 98 |
91 /* go through all pointers and see if they are OK, aborting if not */ | 99 /* go through all pointers and see if they are OK, aborting if not */ |
92 /* always returns 1 if not aborting so that it can be included in */ | 100 /* always returns 1 if not aborting so that it can be included in */ |
93 /* if statement boolean expressions */ | 101 /* if statement boolean expressions */ |
94 int mem_check(char *fname, int linenum) | 102 int mem_check(char *fname, int linenum) |
95 { | 103 { |
104 #ifdef MEM_DEBUG | |
96 STRING_ENTRY *se; | 105 STRING_ENTRY *se; |
97 | 106 |
98 /* scan of a NULL dictionary always succeeds */ | 107 /* scan of a NULL dictionary always succeeds */ |
99 if (allocations == NULL) | 108 if (allocations == NULL) |
100 return TRUE; | 109 return TRUE; |
111 while((se = dict_scan_next(allocations)) != NULL) | 120 while((se = dict_scan_next(allocations)) != NULL) |
112 mem_validate(se->any_ptr); | 121 mem_validate(se->any_ptr); |
113 | 122 |
114 fprintf(trace_file, "+++ --- Done pointer scan\n\n"); | 123 fprintf(trace_file, "+++ --- Done pointer scan\n\n"); |
115 | 124 |
125 #endif | |
116 /* always return a good value if execution arrives here */ | 126 /* always return a good value if execution arrives here */ |
117 return 1; | 127 return 1; |
118 } | 128 } |
119 | 129 |
120 /* allocate some memory and initialize header and trailer */ | 130 /* allocate some memory and initialize header and trailer */ |
121 void *mem_malloc(const size_t bytes) | 131 void *mem_malloc(const size_t bytes) |
122 { | 132 { |
133 #ifdef MEM_DEBUG | |
123 char *mem_temp; | 134 char *mem_temp; |
124 size_t real_size = bytes + (FENCE_SIZE << 1); | 135 size_t real_size = bytes + (FENCE_SIZE << 1); |
125 | 136 |
126 /* allocate including guard bytes to detect some ways of overwriting of memory areas */ | 137 /* allocate including guard bytes to detect some ways of overwriting of memory areas */ |
127 mem_temp = (void *)malloc(real_size); | 138 mem_temp = (void *)malloc(real_size); |
173 if (memdebug_level > 0) { | 184 if (memdebug_level > 0) { |
174 fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp); | 185 fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp); |
175 fflush(trace_file); | 186 fflush(trace_file); |
176 } | 187 } |
177 return (void *)mem_temp; | 188 return (void *)mem_temp; |
189 #else | |
190 return malloc(bytes); | |
191 #endif | |
178 } | 192 } |
179 | 193 |
180 /* release some memory, making sure that it was properly allocated */ | 194 /* release some memory, making sure that it was properly allocated */ |
181 void mem_free(const void *ptr) | 195 void mem_free(const void *ptr) |
182 { | 196 { |
197 #ifdef MEM_DEBUG | |
183 char *mem_temp; | 198 char *mem_temp; |
184 size_t mem_size; | 199 size_t mem_size; |
185 size_t i; | 200 size_t i; |
186 | 201 |
187 if (memdebug_level > 0) | 202 if (memdebug_level > 0) |
236 if (memdebug_level > 0) | 251 if (memdebug_level > 0) |
237 fflush(trace_file); | 252 fflush(trace_file); |
238 | 253 |
239 mem_temp = (char *)ptr - FENCE_SIZE; | 254 mem_temp = (char *)ptr - FENCE_SIZE; |
240 free((void *)mem_temp); | 255 free((void *)mem_temp); |
256 #else | |
257 free((void *) ptr); | |
258 #endif | |
241 } | 259 } |
242 | 260 |
243 /* reallocate some memory, making sure that it was properly allocated */ | 261 /* reallocate some memory, making sure that it was properly allocated */ |
244 void *mem_realloc(const void *ptr, const size_t new_size) | 262 void *mem_realloc(const void *ptr, const size_t new_size) |
245 { | 263 { |
264 #ifdef MEM_DEBUG | |
246 char *mem_temp = (char *)ptr; | 265 char *mem_temp = (char *)ptr; |
247 size_t real_size = new_size + (FENCE_SIZE << 1); | 266 size_t real_size = new_size + (FENCE_SIZE << 1); |
248 size_t mem_size; | 267 size_t mem_size; |
249 long i; | 268 long i; |
250 | 269 |
332 if (memdebug_level > 0) { | 351 if (memdebug_level > 0) { |
333 fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp); | 352 fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp); |
334 fflush(trace_file); | 353 fflush(trace_file); |
335 } | 354 } |
336 return (void *)mem_temp; | 355 return (void *)mem_temp; |
356 #else | |
357 return realloc((void *) ptr, new_size); | |
358 #endif | |
337 } | 359 } |
338 | 360 |
339 /* check a pointer to be sure all check bytes are OK. abort if not */ | 361 /* check a pointer to be sure all check bytes are OK. abort if not */ |
340 /* always returns 1 if not aborting so that it can be included in */ | 362 /* always returns 1 if not aborting so that it can be included in */ |
341 /* if statement boolean expressions */ | 363 /* if statement boolean expressions */ |
342 int mem_validate(const void *ptr) | 364 int mem_validate(const void *ptr) |
343 { | 365 { |
366 #ifdef MEM_DEBUG | |
344 unsigned char *mem_temp = (unsigned char *)ptr; | 367 unsigned char *mem_temp = (unsigned char *)ptr; |
345 size_t mem_size; | 368 size_t mem_size; |
346 size_t i; | 369 size_t i; |
347 | 370 |
348 /* NULL pointers are always valid */ | 371 /* NULL pointers are always valid */ |
414 } | 437 } |
415 abort(); | 438 abort(); |
416 } | 439 } |
417 if (memdebug_level > 0) | 440 if (memdebug_level > 0) |
418 fflush(trace_file); | 441 fflush(trace_file); |
442 #endif | |
419 return 1; | 443 return 1; |
420 } | 444 } |