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