[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     ! 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