Annotation of XML/xmlmemory.c, revision 1.2

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

Webmaster