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 }