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 } |
