Annotation of XML/xmlmemory.c, revision 1.1
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:
! 13: #ifndef NO_XML_MEMORY
! 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:
! 459: #endif /* ! NO_XML_MEMORY */
Webmaster