Annotation of rpm2html/memory.c, revision 1.4

1.1       daniel      1: /*
                      2:  * memory.c: a memory allocator wrapper.
                      3:  *
                      4:  * Daniel.Veillard@w3.org
                      5:  */
                      6: 
                      7: #include <sys/types.h>
                      8: #include <string.h>
                      9: #include <stdio.h>
                     10: #include <malloc.h>
1.4     ! veillard   11: #include <xmlmemory.h>
1.1       daniel     12: #include "memory.h"
1.2       daniel     13: 
                     14: #ifndef NO_DEBUG_MEMORY
1.1       daniel     15: 
                     16: #ifdef debugMalloc
                     17: #undef debugMalloc
                     18: #endif
                     19: #ifdef debugRealloc
                     20: #undef debugRealloc
                     21: #endif
                     22: #ifdef debugStrdup
                     23: #undef debugStrdup
                     24: #endif
                     25: extern void debugMemoryDump(void);
1.4     ! veillard   26: extern int debugInitMemory(void);
1.1       daniel     27: 
                     28: /*
                     29:  * Each of the blocks allocated begin with a header containing informations
                     30:  */
                     31: 
                     32: #define MEMTAG 0x5aa5
                     33: 
                     34: #define MALLOC_TYPE 1
                     35: #define REALLOC_TYPE 2
                     36: #define STRDUP_TYPE 3
                     37: 
                     38: typedef struct memnod {
                     39:     unsigned int   mh_tag;
                     40:     unsigned int   mh_type;
                     41:     unsigned long  mh_number;
                     42:     size_t         mh_size;
                     43: #ifdef MEM_LIST
                     44:    struct memnod *mh_next;
                     45:    struct memnod *mh_prev;
                     46: #endif
                     47:    const char    *mh_file;
                     48:    unsigned int   mh_line;
                     49: }  MEMHDR;
                     50: 
                     51: 
                     52: #ifdef SUN4
                     53: #define ALIGN_SIZE  16
                     54: #else
                     55: #define ALIGN_SIZE  sizeof(double)
                     56: #endif
                     57: #define HDR_SIZE    sizeof(MEMHDR)
                     58: #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
                     59:                      / ALIGN_SIZE ) * ALIGN_SIZE)
                     60: 
                     61: 
                     62: #define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
                     63: #define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
                     64: 
                     65: 
1.4     ! veillard   66: static int initialized = 0;
1.1       daniel     67: static unsigned long  debugMemSize = 0;
                     68: static unsigned long  debugMemSizeMeg = 0;
                     69: static int block=0;
                     70: #ifdef MEM_LIST
                     71: static MEMHDR *memlist = NULL;
                     72: #endif
                     73: 
1.4     ! veillard   74: void mem_tag_error(void *addr);
1.1       daniel     75: #ifdef MEM_LIST
                     76: void  debugmem_list_add(MEMHDR *);
                     77: void debugmem_list_delete(MEMHDR *);
                     78: #endif
1.4     ! veillard   79: #define Mem_Tag_Err(a) mem_tag_error(a);
1.1       daniel     80: 
                     81: /******************************
                     82: #define TEST_POINT {                                           \
                     83:     unsigned long  meg = debugMemSize >> 20;                   \
                     84:     if (meg != debugMemSizeMeg) debugMemoryDump();             \
                     85:     debugMemSizeMeg = meg;                                     \
                     86: }
                     87:  ******************************/
                     88: 
                     89: #ifndef TEST_POINT
                     90: #define TEST_POINT
                     91: #endif
                     92: 
                     93: /*
                     94:  * FUNCTION    : debugMalloc
                     95:  * PURPOSE     : a malloc() equivalent supporting multi-thread access.
                     96:  * INPUT       : an int specifying the size in byte to allocate.
                     97:  * OUTPUT      : none
                     98:  * RESULT      : a pointer to the allocated area or NULL in case of
                     99:  *             lack of memory space.
                    100:  * HISTORY     : 
                    101:  */
                    102: 
                    103: void *
                    104: debugMallocLoc(int size, const char * file, int line)
                    105: {
                    106:     MEMHDR *p;
                    107:     
1.4     ! veillard  108:     if (!initialized)
        !           109:        debugInitMemory();
1.1       daniel    110: #ifdef DEBUG_MEMORY
                    111:     fprintf(stderr, "Malloc(%d)\n",size);
                    112: #endif
                    113: 
                    114:     TEST_POINT
                    115:     
                    116:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
                    117: 
                    118:     if (!p) {
                    119:        fprintf(stderr, "debugMalloc : Out of free space\n");
                    120:        debugMemoryDump();
                    121:     }   
                    122:     p->mh_tag = MEMTAG;
                    123:     p->mh_number = ++block;
                    124:     p->mh_size = size;
                    125:     p->mh_type = MALLOC_TYPE;
                    126:     p->mh_file = file;
                    127:     p->mh_line = line;
                    128:     debugMemSize += size;
                    129: #ifdef MEM_LIST
                    130:     debugmem_list_add(p);
                    131: #endif
                    132: 
                    133: #ifdef DEBUG_MEMORY
                    134:     fprintf(stderr, "Malloc(%d) Ok\n",size);
                    135: #endif
                    136:     
                    137: 
                    138:     TEST_POINT
                    139: 
                    140:     return(HDR_2_CLIENT(p));
                    141: }
                    142: 
                    143: void *
                    144: debugMalloc(int size)
                    145: {
                    146:     return(debugMallocLoc(size, "none", 0));
                    147: }
                    148: 
                    149: /*
                    150:  * debugRealloc : realloc() equivalent.
                    151:  */
                    152:  
                    153: 
                    154: /*
                    155:  * FUNCTION    : debugRealloc
                    156:  * PURPOSE     : a realloc() equivalent supporting multi-thread access.
                    157:  * INPUT       : the initial memory block pointer, and the new size.
                    158:  * OUTPUT      : none
                    159:  * RESULT      : a pointer to the new area or NULL in case of allocation
                    160:  *              error.
                    161:  * HISTORY     : 
                    162:  */
                    163: 
                    164: void *
                    165: debugReallocLoc(void *ptr,int size, const char * file, int line)
                    166: {
                    167:     MEMHDR *p;
                    168:     unsigned long number;
                    169: 
1.4     ! veillard  170:     if (!initialized)
        !           171:        debugInitMemory();
1.1       daniel    172:     TEST_POINT
                    173: 
                    174:     p = CLIENT_2_HDR(ptr);
                    175:     number = p->mh_number;
                    176:     if (p->mh_tag != MEMTAG) {
                    177:          Mem_Tag_Err(p);
                    178:         goto error;
                    179:     }
                    180:     p->mh_tag = ~MEMTAG;
                    181:     debugMemSize -= p->mh_size;
                    182: #ifdef MEM_LIST
                    183:     debugmem_list_delete(p);
                    184: #endif
                    185: 
                    186:     p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
                    187:     if (!p) {
                    188:         goto error;
                    189:     }
                    190:     p->mh_tag = MEMTAG;
                    191:     p->mh_number = number;
                    192:     p->mh_type = REALLOC_TYPE;
                    193:     p->mh_size = size;
                    194:     p->mh_file = file;
                    195:     p->mh_line = line;
                    196:     debugMemSize += size;
                    197: #ifdef MEM_LIST
                    198:     debugmem_list_add(p);
                    199: #endif
                    200: 
                    201:     TEST_POINT
                    202: 
                    203:     return(HDR_2_CLIENT(p));
                    204:     
                    205: error:    
                    206:     return(NULL);
                    207: }
                    208: 
                    209: void *
                    210: debugRealloc(void *ptr,int size) {
                    211:     return(debugReallocLoc(ptr, size, "none", 0));
                    212: }
                    213: 
                    214: /*
                    215:  * debugFree : free() equivalent with error code !
                    216:  */
                    217: 
                    218: 
                    219: /*
                    220:  * FUNCTION    : debugFree
                    221:  * PURPOSE     : an equivalent of free() allowing multi-thread access.
                    222:  * INPUT       : the pointer to the memory block allocated using the
                    223:  *      debugMalloc or debugRealloc functions.
                    224:  * OUTPUT      : none
                    225:  * RESULT      :
                    226:  *               0 : normal result
                    227:  *               EMACHINTER_INVALID_POINTER : the pointer wasn't previously
                    228:  *                     allocated by debugMalloc or debugRealloc.
                    229:  *               or initialization or internal error.
                    230:  * HISTORY     : 
                    231:  */
                    232: 
                    233: int
                    234: debugFree(void *ptr)
                    235: {
                    236:     MEMHDR *p;
                    237:     int ret;
                    238: 
1.4     ! veillard  239:     if (!initialized)
        !           240:        debugInitMemory();
1.1       daniel    241:     TEST_POINT
                    242: 
                    243:     p = CLIENT_2_HDR(ptr);
                    244:     if (p->mh_tag != MEMTAG) {
                    245:          Mem_Tag_Err(p);
                    246:          ret = -1;
                    247:          goto error;
                    248:     }
                    249:     p->mh_tag = ~MEMTAG;
                    250:     debugMemSize -= p->mh_size;
                    251: 
                    252: #ifdef MEM_LIST
                    253:     debugmem_list_delete(p);
                    254: #endif
                    255:     free(p);
                    256: 
                    257:     TEST_POINT
                    258: 
                    259:     ret = 0;
                    260:     return(ret);
                    261:     
                    262: error:    
                    263:     return(ret);
                    264: }
                    265: 
                    266: /*
                    267:  * debugStrdup : strdup() equivalent.
                    268:  */
                    269: 
                    270: 
                    271: /*
                    272:  * FUNCTION    : debugStrdup
                    273:  * PURPOSE     : a strdup() equivalent supporting multi-thread access.
                    274:  * INPUT       : the null terminated string to duplicate.
                    275:  * OUTPUT      : none
                    276:  * RESULT      : a T_Char pointer referencing the new string or NULL
                    277:  *  if allocation error occurs.
                    278:  * HISTORY     : 
                    279:  */
                    280: 
                    281: char *
                    282: debugStrdupLoc(const char *str, const char *file, int line)
                    283: {
                    284:     char *s;
                    285:     size_t size = strlen(str) + 1;
                    286:     MEMHDR *p;
                    287: 
1.4     ! veillard  288:     if (!initialized)
        !           289:        debugInitMemory();
1.1       daniel    290:     TEST_POINT
                    291: 
                    292:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
                    293:     if (!p) {
                    294:         goto error;
                    295:     }
                    296:     p->mh_tag = MEMTAG;
                    297:     p->mh_number = ++block;
                    298:     p->mh_size = size;
                    299:     p->mh_type = STRDUP_TYPE;
                    300:     p->mh_file = file;
                    301:     p->mh_line = line;
                    302:     debugMemSize += size;
                    303: #ifdef MEM_LIST
                    304:     debugmem_list_add(p);
                    305: #endif
                    306:     s = HDR_2_CLIENT(p);
                    307:     
                    308:     if (s != NULL)
                    309:         strcpy(s,str);
                    310:     else
                    311:         goto error;
                    312:     
                    313:     TEST_POINT
                    314: 
                    315:     return(s);
                    316: 
                    317: error:
                    318:     return(NULL);
                    319: }
                    320: 
                    321: char *
                    322: debugStrdup(const char *str) {
                    323:     return(debugStrdupLoc(str, "none", 0));
                    324: }
                    325: 
                    326: /*
                    327:  * FUNCTION    : debugMemUsed
                    328:  * PURPOSE     : returns the amount of memory currenly allocated using
                    329:  *  debugMalloc, debugRealloc and debugStrdup.
                    330:  * INPUT       : none
                    331:  * OUTPUT      : none
                    332:  * RESULT      : a 32 bits integer representing the amount of memory allocated.
                    333:  * HISTORY     : 
                    334:  */
                    335: 
                    336: int
                    337: debugMemUsed(void) {
1.4     ! veillard  338:     if (!initialized)
        !           339:        debugInitMemory();
1.1       daniel    340:      return(debugMemSize);
                    341: }
                    342: 
                    343: 
                    344: /*
                    345:  * FUNCTION    : debugMemDisplay
                    346:  * PURPOSE     : show in-extenso the memory allocated using
                    347:  *  debugMalloc, debugRealloc and debugStrdup.
                    348:  * INPUT       : a FILE descriptor used as the output file, if NULL
                    349:  *  the result is written to the file .memorylist ...
                    350:  * OUTPUT      : 
                    351:  * RESULT      :
                    352:  *               0 : normal result
                    353:  * HISTORY     : 
                    354:  */
                    355: 
                    356: void
                    357: debugMemDisplay(FILE *fp)
                    358: {
1.4     ! veillard  359:     if (!initialized)
        !           360:        debugInitMemory();
1.1       daniel    361: #ifdef MEM_LIST
                    362:       MEMHDR *p;
                    363:       int     idx;
                    364:     
                    365:       fprintf(fp,"      MEMORY ALLOCATED : %lu\n",debugMemSize);
                    366:       fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
                    367:       idx = 0;
                    368:       p = memlist;
                    369:       while (p) {
                    370:          fprintf(fp,"%-5u  %6lu %6u ",idx++,p->mh_number,p->mh_size);
                    371:           switch (p->mh_type) {
                    372:              case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
                    373:              case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
                    374:             case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
                    375:                       default:fprintf(fp,"   ???    in ");break;
                    376:           }
                    377:          if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
                    378:           if (p->mh_tag != MEMTAG)
                    379:              fprintf(fp,"  INVALID");
                    380:           fprintf(fp,"\n");
                    381:           p = p->mh_next;
                    382:       }
                    383: #else
                    384:       fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
                    385: #endif
                    386: }
                    387: 
                    388: #ifdef MEM_LIST
                    389: 
                    390: void debugmem_list_add(MEMHDR *p)
                    391: {
                    392:        p->mh_next = memlist;
                    393:        p->mh_prev = NULL;
                    394:        if (memlist) memlist->mh_prev = p;
                    395:        memlist = p;
                    396: #ifdef MEM_LIST_DEBUG
                    397:        if (stderr)
                    398:        Mem_Display(stderr);
                    399: #endif
                    400: }
                    401: 
                    402: void debugmem_list_delete(MEMHDR *p)
                    403: {
                    404:        if (p->mh_next)
                    405:        p->mh_next->mh_prev = p->mh_prev;
                    406:        if (p->mh_prev)
                    407:        p->mh_prev->mh_next = p->mh_next;
                    408:        else memlist = p->mh_next;
                    409: #ifdef MEM_LIST_DEBUG
                    410:        if (stderr)
                    411:        Mem_Display(stderr);
                    412: #endif
                    413: }
                    414: 
                    415: #endif
                    416: 
                    417: /*
1.4     ! veillard  418:  * mem_tag_error : internal error function.
1.1       daniel    419:  */
                    420:  
1.4     ! veillard  421: void mem_tag_error(void *p)
1.1       daniel    422: {
1.4     ! veillard  423:     if (!initialized)
        !           424:        debugInitMemory();
        !           425:     fprintf(stderr, "Memory tag error occurs :%p \n\t bye\n", p);
1.1       daniel    426: #ifdef MEM_LIST
1.4     ! veillard  427:     if (stderr)
        !           428:         debugMemDisplay(stderr);
1.1       daniel    429: #endif
                    430: }
                    431: 
1.3       daniel    432: FILE *debugMemoryDumpFile = NULL;
1.1       daniel    433: 
                    434: /*
                    435:  * FUNCTION    : debugMemoryDump
                    436:  * PURPOSE     : saves informations concerning memory allocation
                    437:  *               in a ".memdump" file.
                    438:  * INPUT       : none
                    439:  * OUTPUT      : none
                    440:  * RESULT      : none
                    441:  * HISTORY     : 
                    442:  */
                    443: 
                    444: void
                    445: debugMemoryDump(void)
                    446: {
                    447:     FILE *dump;
                    448: 
1.4     ! veillard  449:     if (!initialized)
        !           450:        debugInitMemory();
1.1       daniel    451:     dump = fopen(".memdump", "w");
                    452:     if (dump == NULL) debugMemoryDumpFile = stdout;
                    453:     else debugMemoryDumpFile = dump;
                    454: 
                    455:     debugMemDisplay(debugMemoryDumpFile);
                    456: 
                    457:     if (dump != NULL) fclose(dump);
                    458: }
                    459: 
                    460: 
                    461: /****************************************************************
                    462:  *                                                             *
                    463:  *             Initialization Routines                         *
                    464:  *                                                             *
                    465:  ****************************************************************/
                    466: 
                    467: 
                    468: /*
                    469:  * debugInitMemory : initialize the memory allocator.
                    470:  */
                    471: 
                    472: 
                    473: /*
                    474:  * FUNCTION    : debugInitMemory
                    475:  * PURPOSE     : initialize the memory allocator.
                    476:  * INPUT       : none
                    477:  * OUTPUT      : none
                    478:  * RESULT      :
                    479:  *               0 : normal result
                    480:  * HISTORY     : 
                    481:  */
                    482: 
                    483: int
                    484: debugInitMemory(void)
                    485: {
                    486:      int ret;
1.4     ! veillard  487:      xmlFreeFunc freeFunc;
        !           488:      xmlMallocFunc mallocFunc;
        !           489:      xmlReallocFunc reallocFunc;
        !           490:      xmlStrdupFunc strdupFunc;
1.1       daniel    491:     
                    492: #ifdef DEBUG_MEMORY
                    493:      fprintf(stderr, "debugInitMemory() Ok\n");
                    494: #endif     
1.4     ! veillard  495:      xmlMemSetup(debugFree, debugMalloc, debugRealloc, debugStrdup);
        !           496:      xmlMemGet(&freeFunc, &mallocFunc, &reallocFunc, &strdupFunc);
        !           497:      if ((freeFunc != debugFree) ||
        !           498:         (mallocFunc != debugMalloc) ||
        !           499:         (reallocFunc != debugRealloc) ||
        !           500:         (strdupFunc != debugStrdup)) {
        !           501:         fprintf(stderr, "debugInitMemory: xml memory allocator problem\n");
        !           502:         exit(1);
        !           503:      }
        !           504:      initialized = 1;
1.1       daniel    505:      ret = 0;
                    506:      return(ret);
                    507: }
                    508: 
                    509: #endif /* ! NO_DEBUG_MEMORY */

Webmaster