[BACK]Return to memory.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / urogue

Annotation of early-roguelike/urogue/memory.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:     memory.c
                      3:
                      4:     UltraRogue: The Ultimate Adventure in the Dungeons of Doom
                      5:     Copyright (C) 1995 Herb Chong
                      6:     All rights reserved.
                      7:
                      8:     See the file LICENSE.TXT for full copyright and licensing information.
                      9: */
                     10:
                     11: #include <stdio.h>
                     12: #include <stdlib.h>
                     13:
                     14: #include "dict.h"
                     15: #include "memory.h"
                     16: #include "rogue.h"
                     17:
                     18: #ifdef HAVE_CONFIG_H
                     19: #include "config.h"
                     20: #endif
                     21:
                     22: static char sccsid[] = "%W%\t%G%";
                     23:
                     24: /*     Debugging memory allocation code that tries to trap common memory problems
                     25:        like overwriting storage and stepping on memory pointer chains. If code
                     26:        doesn't use malloc, free, and realloc a lot, these routines can be left in
                     27:        as added protection against undetected storage bugs.
                     28: */
                     29:
                     30: /*     FENCE_SIZE should be a multiple of sizeof(size_t) to prevent alignment problems.
                     31:        The code assumes that malloc and realloc return pointers aligned at least on size_t
                     32:        sized boundaries and that a pointer needs alignment no more strict than that of an
                     33:        object needed to hold a size_t.
                     34: */
                     35:
                     36: #define FENCE_SIZE (sizeof(size_t) * 1024)
                     37:
                     38: static int memdebug_level = 0;
                     39: static DICTIONARY *allocations = NULL;
                     40: static FILE *trace_file = NULL;
                     41:
                     42: /* set the debug level */
                     43: void mem_debug(const int level)
                     44: {
                     45:        memdebug_level = level;
                     46:
                     47: #ifdef MEM_DEBUG
                     48:        if (trace_file == NULL)
                     49:                trace_file = fopen("trace", "w");
                     50:
                     51:        /* all except 0, 1, and unknown fall through */
                     52:        switch(memdebug_level) {
                     53:        case 2:
                     54:                fprintf(trace_file, "+++ Memory tracking possible, ");
                     55:        case 1:
                     56:                fprintf(trace_file, "+++ Memory debugging enabled, ");
                     57:                break;
                     58:        case 0:
                     59:                fprintf(trace_file, "+++ Memory debugging disabled, ");
                     60:                break;
                     61:        default:
                     62:                fprintf(trace_file, "!!! Unknown memory debug level set, enabling level 1, ");
                     63:                memdebug_level = 1;
                     64:                break;
                     65:        }
                     66:        fprintf(trace_file, "fence size = %d\n", FENCE_SIZE);
                     67: #endif
                     68: }
                     69:
                     70: /* set memory tracking on or off */
                     71: /* turning it off deletes all tracking data */
                     72: void mem_tracking(int flag)
                     73: {
                     74: #ifdef MEM_DEBUG
                     75:        /* do nothing if debuglevel is too low */
                     76:        if (memdebug_level < 2)
                     77:                return;
                     78:
                     79:        /* turn on tracking */
                     80:        if (flag > 0) {
                     81:                if (allocations != NULL) {
                     82:                        dict_destroy(allocations);
                     83:                        allocations = NULL;
                     84:                }
                     85:                allocations = dict_create(8, 100, 4, 20);
                     86:                if (allocations == NULL) {
                     87:                        fprintf(trace_file, "!!! Unable to allocate tracking table!\n");
                     88:                        abort();
                     89:                }
                     90:        }
                     91:        /* turn off tracking */
                     92:        else if (allocations != NULL) {
                     93:                dict_destroy(allocations);
                     94:                allocations = NULL;
                     95:        }
                     96: #endif
                     97: }
                     98:
                     99: /* go through all pointers and see if they are OK, aborting if not */
                    100: /* always returns 1 if not aborting so that it can be included in  */
                    101: /* if statement boolean expressions */
                    102: int mem_check(char *fname, int linenum)
                    103: {
                    104: #ifdef MEM_DEBUG
                    105:        STRING_ENTRY *se;
                    106:
                    107:        /* scan of a NULL dictionary always succeeds */
                    108:        if (allocations == NULL)
                    109:                return TRUE;
                    110:
                    111:        if (!dict_scan_begin(allocations)) {
                    112:                fprintf(trace_file, "!!! Dictionary scan initialization failed!\n");
                    113:                abort();
                    114:        }
                    115:
                    116:        fprintf(trace_file, "\n+++ --- Starting pointer scan\n");
                    117:        fprintf(trace_file, "+++ --- At %s, %d\n", fname, linenum);
                    118:
                    119:        /* mem_validate aborts if there is a problem */
                    120:        while((se = dict_scan_next(allocations)) != NULL)
                    121:                mem_validate(se->any_ptr);
                    122:
                    123:        fprintf(trace_file, "+++ --- Done pointer scan\n\n");
                    124:
                    125: #endif
                    126:        /* always return a good value if execution arrives here */
                    127:        return 1;
                    128: }
                    129:
                    130: /* allocate some memory and initialize header and trailer */
                    131: void *mem_malloc(const size_t bytes)
                    132: {
                    133: #ifdef MEM_DEBUG
                    134:        char *mem_temp;
                    135:        size_t real_size = bytes + (FENCE_SIZE << 1);
                    136:
                    137:        /* allocate including guard bytes to detect some ways of overwriting of memory areas */
                    138:        mem_temp = (void *)malloc(real_size);
                    139:        if (memdebug_level > 0) {
                    140:                fprintf(trace_file, "+++ Requested size of %ld bytes\n", bytes);
                    141:                fprintf(trace_file, "+++ Actual malloc of %ld bytes located at %p\n", real_size, mem_temp);
                    142:        }
                    143:
                    144:        /* if allocation succeeded, set management data */
                    145:        if (mem_temp != NULL) {
                    146:                size_t i;
                    147:                char *end;
                    148:
                    149:                /* do beginning marker bytes */
                    150:                for (i = 0; i < FENCE_SIZE - sizeof(size_t); i++)
                    151:                        *mem_temp++ = 145;
                    152:
                    153:                /* save size in header too */
                    154:                if (memdebug_level > 0)
                    155:                        fprintf(trace_file, "*** Requested memory size stored at %p\n", mem_temp);
                    156:                *(size_t *)mem_temp = bytes;
                    157:
                    158:                /* finally, point to storage we are going to hand out */
                    159:                mem_temp += sizeof(size_t);
                    160:
                    161:                /* now, point to trailer bytes and do them */
                    162:                end = mem_temp + bytes;
                    163:                for (i = 0; i < FENCE_SIZE; i++)
                    164:                        *end++ = 145;
                    165:
                    166:                /* now zap contents to zero */
                    167:                for (i = 0; i < bytes; i++)
                    168:                        mem_temp[i] = 0;
                    169:        }
                    170:
                    171:        /* track pointer if needed */
                    172:        if (memdebug_level > 1 && allocations != NULL) {
                    173:                char key[16];
                    174:                long temp;
                    175:
                    176:                sprintf(key, "%p", mem_temp);
                    177:                if (dict_insert(allocations, key, 1, (const unsigned long) bytes, mem_temp, &temp) == NULL) {
                    178:                        fprintf(trace_file, "!!! Insert of pointer tracking info failed\n");
                    179:                        abort();
                    180:                }
                    181:        }
                    182:
                    183:        /* allow caller to do error handling */
                    184:        if (memdebug_level > 0) {
                    185:                fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp);
                    186:                fflush(trace_file);
                    187:        }
                    188:        return (void *)mem_temp;
                    189: #else
                    190:        return malloc(bytes);
                    191: #endif
                    192: }
                    193:
                    194: /* release some memory, making sure that it was properly allocated */
                    195: void mem_free(const void *ptr)
                    196: {
                    197: #ifdef MEM_DEBUG
                    198:        char *mem_temp;
                    199:        size_t mem_size;
                    200:        size_t i;
                    201:
                    202:        if (memdebug_level > 0)
                    203:                fprintf(trace_file, "+++ Free of memory located at %p\n", ptr);
                    204:        if (ptr == NULL) {
                    205:                if (memdebug_level > 0) {
                    206:                        fprintf(trace_file, "!!! Freeing NULL pointer\n");
                    207:                        fflush(trace_file);
                    208:                }
                    209:                abort();
                    210:        }
                    211:
                    212:        mem_validate(ptr);      /* doesn't return on error */
                    213:
                    214:        /* get location of size of area */
                    215:        mem_temp = (char *)ptr - sizeof(size_t);
                    216:
                    217:        /* get and calculate real size */
                    218:        mem_size = *(size_t *)mem_temp + (FENCE_SIZE << 1);
                    219:
                    220:        /* if doing memory tracking */
                    221:        if (memdebug_level > 1 && allocations != NULL) {
                    222:                char key[16];
                    223:                STRING_ENTRY *se;
                    224:                long temp;
                    225:
                    226:                sprintf(key, "%p", ptr);
                    227:
                    228:                if ((se = dict_search(allocations, key, &temp)) == NULL) {
                    229:                        fprintf(trace_file, "!!! Deleting pointer not found in tracking info\n");
                    230:                        abort();
                    231:                }
                    232:
                    233:                if (se->count == 0) {
                    234:                        fprintf(trace_file, "!!! Freeing a pointer that has already been freed!\n");
                    235:                        abort();
                    236:                }
                    237:                else if (se->flags != mem_size - (FENCE_SIZE << 1)) {
                    238:                        fprintf(trace_file, "!!! Stored size different from tracking size!\n");
                    239:                        abort();
                    240:                }
                    241:
                    242:                /* remember deleted stuff by zeroing the allocation count */
                    243:                se->count = 0;
                    244:                se->flags = 0;
                    245:        }
                    246:
                    247:        /* zap bytes being freed */
                    248:        for (i = 0, mem_temp = (char *)ptr - FENCE_SIZE; i < mem_size; i++, mem_temp++)
                    249:                *mem_temp = 243;
                    250:
                    251:        if (memdebug_level > 0)
                    252:                fflush(trace_file);
                    253:
                    254:        mem_temp = (char *)ptr - FENCE_SIZE;
                    255:        free((void *)mem_temp);
                    256: #else
                    257:        free((void *) ptr);
                    258: #endif
                    259: }
                    260:
                    261: /* reallocate some memory, making sure that it was properly allocated */
                    262: void *mem_realloc(const void *ptr, const size_t new_size)
                    263: {
                    264: #ifdef MEM_DEBUG
                    265:        char *mem_temp = (char *)ptr;
                    266:        size_t real_size = new_size + (FENCE_SIZE << 1);
                    267:        size_t mem_size;
                    268:        long i;
                    269:
                    270:        if (memdebug_level > 0) {
                    271:                fprintf(trace_file, "+++ Requested size of %ld bytes\n", new_size);
                    272:                fprintf(trace_file, "+++ Actual realloc of %ld bytes located at %p\n", real_size, mem_temp);
                    273:        }
                    274:        if (ptr == NULL) {
                    275:                if (memdebug_level > 0) {
                    276:                        fprintf(trace_file, "!!! Reallocating NULL pointer\n");
                    277:                        fflush(trace_file);
                    278:                }
                    279:                abort();
                    280:        }
                    281:
                    282:        mem_validate(ptr);      /* doesn't return on error */
                    283:
                    284:        /* if doing memory tracking */
                    285:        if (memdebug_level > 1 && allocations != NULL) {
                    286:                char key[16];
                    287:                STRING_ENTRY *se;
                    288:                long temp;
                    289:
                    290:                sprintf(key, "%p", ptr);
                    291:
                    292:                if ((se = dict_search(allocations, key, &temp)) == NULL) {
                    293:                        fprintf(trace_file, "!!! Deleting a pointer not found in tracking info!\n");
                    294:                        abort();
                    295:                }
                    296:
                    297:                /* point to size bytes */
                    298:                mem_temp = (char *)ptr - sizeof(size_t);
                    299:
                    300:                /* get user size */
                    301:                mem_size = *(size_t *)mem_temp;
                    302:
                    303:                if (se->count == 0) {
                    304:                        fprintf(trace_file, "!!! Freeing a pointer that has already been freed!\n");
                    305:                        abort();
                    306:                }
                    307:                else if (se->flags != mem_size) {
                    308:                        fprintf(trace_file, "!!! Stored size different from tracking size!\n");
                    309:                        abort();
                    310:                }
                    311:
                    312:                /* remember deleted stuff by zeroing the allocation count */
                    313:                se->count = 0;
                    314:                se->flags = 0;
                    315:        }
                    316:
                    317:
                    318:        /* header marker bytes will be copied by the realloc */
                    319:        mem_temp = (char *)ptr - FENCE_SIZE;
                    320:        mem_temp = realloc((void *)mem_temp, real_size);
                    321:
                    322:        if (mem_temp != NULL) {
                    323:                char *end;
                    324:
                    325:                /* save size in header too */
                    326:                mem_temp += FENCE_SIZE - sizeof(size_t);
                    327:                if (memdebug_level > 0)
                    328:                        fprintf(trace_file, "*** Requested memory size stored at %p\n", mem_temp);
                    329:                *(size_t *)mem_temp = new_size;
                    330:
                    331:                /* finally, point to storage we are going to hand out */
                    332:                mem_temp += sizeof(size_t);
                    333:
                    334:                /* now, point to trailer bytes and do them */
                    335:                end = mem_temp + new_size;
                    336:                for (i = 0; i < FENCE_SIZE; i++)
                    337:                        *end++ = 145;
                    338:        }
                    339:
                    340:        if (memdebug_level > 1 && allocations != NULL) {
                    341:                char key[16];
                    342:                long temp;
                    343:
                    344:                sprintf(key, "%p", mem_temp);
                    345:                if (dict_insert(allocations, key, 1, (const unsigned long)new_size, mem_temp, &temp) == NULL) {
                    346:                        fprintf(trace_file, "!!! Insert of pointer tracking info failed\n");
                    347:                        abort();
                    348:                }
                    349:        }
                    350:
                    351:        if (memdebug_level > 0) {
                    352:                fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp);
                    353:                fflush(trace_file);
                    354:        }
                    355:        return (void *)mem_temp;
                    356: #else
                    357:        return realloc((void *) ptr, new_size);
                    358: #endif
                    359: }
                    360:
                    361: /* check a pointer to be sure all check bytes are OK. abort if not */
                    362: /* always returns 1 if not aborting so that it can be included in  */
                    363: /* if statement boolean expressions */
                    364: int mem_validate(const void *ptr)
                    365: {
                    366: #ifdef MEM_DEBUG
                    367:        unsigned char *mem_temp = (unsigned char *)ptr;
                    368:        size_t mem_size;
                    369:        size_t i;
                    370:
                    371:        /* NULL pointers are always valid */
                    372:        if (ptr == NULL)
                    373:                return 1;
                    374:
                    375:        if (memdebug_level > 0)
                    376:                fprintf(trace_file, "+++ Checking %p as pointer\n", ptr);
                    377:
                    378:
                    379:        if (memdebug_level > 1 && allocations != NULL) {
                    380:                char key[16];
                    381:                STRING_ENTRY *se;
                    382:                long temp;
                    383:
                    384:                sprintf(key, "%p", ptr);
                    385:
                    386:                if ((se = dict_search(allocations, key, &temp)) == NULL) {
                    387:                        fprintf(trace_file, "!!! Pointer not found in tracking info!\n");
                    388:                        abort();
                    389:                }
                    390:
                    391:                /* point to size bytes */
                    392:                mem_temp = (unsigned char *)ptr - sizeof(size_t);
                    393:
                    394:                /* get user size */
                    395:                mem_size = *(size_t *)mem_temp;
                    396:
                    397:                if (se->count == 0) {
                    398:                        fprintf(trace_file, "!!! Checking pointer has been freed!\n");
                    399:                        abort();
                    400:                }
                    401:                else if (se->flags != mem_size) {
                    402:                        fprintf(trace_file, "!!! Stored size different from tracking size!\n");
                    403:                        abort();
                    404:                }
                    405:        }
                    406:
                    407:        /* check the header bytes */
                    408:        mem_temp = (unsigned char *) ptr - FENCE_SIZE;
                    409:        if (memdebug_level > 0)
                    410:                fprintf(trace_file, "+++ Real pointer at %p\n", mem_temp);
                    411:
                    412:
                    413:        for (i = 0; i < FENCE_SIZE - sizeof(size_t); i++)
                    414:                if (*mem_temp++ != 145) {
                    415:                        if (memdebug_level > 0) {
                    416:                                fprintf(trace_file, "!!! The user pointer at %p has been overwritten\n", ptr);
                    417:                                fprintf(trace_file, "!!! Header offset %ld has been changed\n", i - 1);
                    418:                                fflush(trace_file);
                    419:                        }
                    420:                        abort();
                    421:                }
                    422:
                    423:        /* check size */
                    424:        i = *(size_t *)mem_temp;
                    425:        if (memdebug_level > 0)
                    426:                fprintf(trace_file, "*** Stored memory size of %ld bytes in header\n", i);
                    427:
                    428:
                    429:        /* now point to where trailer should be */
                    430:        mem_temp = (unsigned char *)ptr + i;
                    431:        for (i = 0; i < FENCE_SIZE; i++)
                    432:                if (*mem_temp++ != 145) {
                    433:                        if (memdebug_level > 0) {
                    434:                                fprintf(trace_file, "!!! The user pointer at %p has been overwritten\n", ptr);
                    435:                                fprintf(trace_file, "!!! Trailer offset %ld has been changed\n", i - 1);
                    436:                                fflush(trace_file);
                    437:                        }
                    438:                        abort();
                    439:                }
                    440:        if (memdebug_level > 0)
                    441:                fflush(trace_file);
                    442: #endif
                    443:        return 1;
                    444: }

CVSweb