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