Annotation of XML/xmlmemory.c, revision 1.6
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: #ifdef xmlMalloc
31: #undef xmlMalloc
32: #endif
33: #ifdef xmlRealloc
34: #undef xmlRealloc
35: #endif
36: #ifdef xmlMemStrdup
37: #undef xmlMemStrdup
38: #endif
1.6 ! daniel 39:
1.1 daniel 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: void
238: xmlFree(void *ptr)
239: {
240: MEMHDR *p;
241:
242: TEST_POINT
243:
244: p = CLIENT_2_HDR(ptr);
245: if (p->mh_tag != MEMTAG) {
1.4 daniel 246: Mem_Tag_Err(p);
247: goto error;
1.1 daniel 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: return;
260:
261: error:
262: fprintf(stderr, "xmlFree(%X) error\n", (unsigned int) ptr);
263: return;
264: }
265:
266: /**
267: * xmlMemStrdupLoc:
268: * @ptr: the initial string pointer
269: * @file: the file name or NULL
270: * @file: the line number
271: *
272: * a strdup() equivalent, with logging of the allocation info.
273: *
274: * Returns a pointer to the new string or NULL if allocation error occured.
275: */
276:
277: char *
278: xmlMemStrdupLoc(const char *str, const char *file, int line)
279: {
280: char *s;
281: size_t size = strlen(str) + 1;
282: MEMHDR *p;
283:
284: TEST_POINT
285:
286: p = (MEMHDR *) malloc(RESERVE_SIZE+size);
287: if (!p) {
1.4 daniel 288: goto error;
1.1 daniel 289: }
290: p->mh_tag = MEMTAG;
291: p->mh_number = ++block;
292: p->mh_size = size;
293: p->mh_type = STRDUP_TYPE;
294: p->mh_file = file;
295: p->mh_line = line;
296: debugMemSize += size;
297: #ifdef MEM_LIST
298: debugmem_list_add(p);
299: #endif
300: s = HDR_2_CLIENT(p);
301:
302: if (s != NULL)
1.4 daniel 303: strcpy(s,str);
1.1 daniel 304: else
1.4 daniel 305: goto error;
1.1 daniel 306:
307: TEST_POINT
308:
309: return(s);
310:
311: error:
312: return(NULL);
313: }
314:
315: /**
316: * xmlMemStrdup:
317: * @ptr: the initial string pointer
318: *
319: * a strdup() equivalent, with logging of the allocation info.
320: *
321: * Returns a pointer to the new string or NULL if allocation error occured.
322: */
323:
324: char *
325: xmlMemStrdup(const char *str) {
326: return(xmlMemStrdupLoc(str, "none", 0));
327: }
328:
329: /**
330: * xmlMemUsed:
331: *
332: * returns the amount of memory currenly allocated
333: *
334: * Returns an int representing the amount of memory allocated.
335: */
336:
337: int
338: xmlMemUsed(void) {
339: return(debugMemSize);
340: }
341:
342: /**
343: * xmlMemDisplay:
344: * @fp: a FILE descriptor used as the output file, if NULL, the result is
345: 8 written to the file .memorylist
346: *
347: * show in-extenso the memory blocks allocated
348: */
349:
350: void
351: xmlMemDisplay(FILE *fp)
352: {
353: #ifdef MEM_LIST
1.4 daniel 354: MEMHDR *p;
355: int idx;
356: #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
1.5 daniel 357: time_t currentTime;
1.4 daniel 358: char buf[500];
359: struct tm * tstruct;
360:
1.5 daniel 361: currentTime = time(NULL);
362: tstruct = localtime(¤tTime);
1.4 daniel 363: strftime(buf, sizeof(buf) - 1, "%c", tstruct);
364: fprintf(fp," %s\n\n", buf);
365: #endif
366:
1.1 daniel 367:
1.4 daniel 368: fprintf(fp," MEMORY ALLOCATED : %lu\n",debugMemSize);
369: fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
370: idx = 0;
371: p = memlist;
372: while (p) {
1.1 daniel 373: fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
1.4 daniel 374: switch (p->mh_type) {
375: case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
376: case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
377: case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
378: default:fprintf(fp," ??? in ");break;
379: }
1.1 daniel 380: if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
1.4 daniel 381: if (p->mh_tag != MEMTAG)
1.1 daniel 382: fprintf(fp," INVALID");
1.4 daniel 383: fprintf(fp,"\n");
384: p = p->mh_next;
385: }
1.1 daniel 386: #else
1.4 daniel 387: fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
1.1 daniel 388: #endif
389: }
390:
391: #ifdef MEM_LIST
392:
393: void debugmem_list_add(MEMHDR *p)
394: {
1.4 daniel 395: p->mh_next = memlist;
396: p->mh_prev = NULL;
397: if (memlist) memlist->mh_prev = p;
398: memlist = p;
1.1 daniel 399: #ifdef MEM_LIST_DEBUG
1.4 daniel 400: if (stderr)
401: Mem_Display(stderr);
1.1 daniel 402: #endif
403: }
404:
405: void debugmem_list_delete(MEMHDR *p)
406: {
1.4 daniel 407: if (p->mh_next)
408: p->mh_next->mh_prev = p->mh_prev;
409: if (p->mh_prev)
410: p->mh_prev->mh_next = p->mh_next;
411: else memlist = p->mh_next;
1.1 daniel 412: #ifdef MEM_LIST_DEBUG
1.4 daniel 413: if (stderr)
414: Mem_Display(stderr);
1.1 daniel 415: #endif
416: }
417:
418: #endif
419:
420: /*
421: * debugmem_tag_error : internal error function.
422: */
423:
424: void debugmem_tag_error(void *p)
425: {
1.4 daniel 426: fprintf(stderr, "Memory tag error occurs :%p \n\t bye\n", p);
1.1 daniel 427: #ifdef MEM_LIST
1.4 daniel 428: if (stderr)
429: xmlMemDisplay(stderr);
1.1 daniel 430: #endif
431: }
432:
433: FILE *xmlMemoryDumpFile = NULL;
434:
435:
436: /**
437: * xmlMemoryDump:
438: *
439: * Dump in-extenso the memory blocks allocated to the file .memorylist
440: */
441:
442: void
443: xmlMemoryDump(void)
444: {
445: FILE *dump;
446:
447: dump = fopen(".memdump", "w");
448: if (dump == NULL) xmlMemoryDumpFile = stdout;
449: else xmlMemoryDumpFile = dump;
450:
451: xmlMemDisplay(xmlMemoryDumpFile);
452:
453: if (dump != NULL) fclose(dump);
454: }
455:
456:
457: /****************************************************************
458: * *
459: * Initialization Routines *
460: * *
461: ****************************************************************/
462:
463: /**
464: * xmlInitMemory:
465: *
466: * Initialize the memory layer.
1.6 ! daniel 467: *
! 468: * Returns 0 on success
1.1 daniel 469: */
470:
471:
472: int
473: xmlInitMemory(void)
474: {
475: int ret;
476:
477: #ifdef DEBUG_MEMORY
478: fprintf(stderr, "xmlInitMemory() Ok\n");
479: #endif
480: ret = 0;
481: return(ret);
482: }
483:
1.2 daniel 484: #endif /* ! NO_DEBUG_MEMORY */
Webmaster