blob: 5527668627cf25e53d7fae1d21c9e816525a072d [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
Daniel Veillard26908ab2002-01-01 16:50:03 +00002 * xmlmemory.c: libxml memory allocator wrapper.
Owen Taylor3473f882001-02-23 17:55:21 +00003 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00004 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +00005 */
6
Daniel Veillard34ce8be2002-03-18 19:37:11 +00007#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +00008#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +00009
Owen Taylor3473f882001-02-23 17:55:21 +000010#include <string.h>
11
12#ifdef HAVE_SYS_TYPES_H
13#include <sys/types.h>
14#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000015
Owen Taylor3473f882001-02-23 17:55:21 +000016#ifdef HAVE_TIME_H
17#include <time.h>
18#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000019
20#ifdef HAVE_STDLIB_H
21#include <stdlib.h>
22#else
Owen Taylor3473f882001-02-23 17:55:21 +000023#ifdef HAVE_MALLOC_H
24#include <malloc.h>
25#endif
Owen Taylor3473f882001-02-23 17:55:21 +000026#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000027
Owen Taylor3473f882001-02-23 17:55:21 +000028#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
31
Daniel Veillard70cab352002-02-06 16:06:58 +000032/**
33 * MEM_LIST:
34 *
35 * keep track of all allocated blocks for error reporting
36 * Always build the memory list !
37 */
38#ifndef MEM_LIST
39#define MEM_LIST /* keep a list of all the allocated memory blocks */
40#endif
Owen Taylor3473f882001-02-23 17:55:21 +000041
42#include <libxml/xmlmemory.h>
Daniel Veillardd0463562001-10-13 09:15:48 +000043#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000044#include <libxml/xmlerror.h>
45
Daniel Veillard56a4cb82001-03-24 17:00:36 +000046void xmlMallocBreakpoint(void);
Daniel Veillard8599e702001-07-17 21:38:51 +000047void * xmlMemMalloc(size_t size);
Daniel Veillard8599e702001-07-17 21:38:51 +000048void * xmlMemRealloc(void *ptr,size_t size);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000049void xmlMemFree(void *ptr);
50char * xmlMemoryStrdup(const char *str);
51
52/************************************************************************
53 * *
54 * Macros, variables and associated types *
55 * *
56 ************************************************************************/
57
58
Owen Taylor3473f882001-02-23 17:55:21 +000059#ifdef xmlMalloc
60#undef xmlMalloc
61#endif
62#ifdef xmlRealloc
63#undef xmlRealloc
64#endif
65#ifdef xmlMemStrdup
66#undef xmlMemStrdup
67#endif
68
69
70/*
71 * Each of the blocks allocated begin with a header containing informations
72 */
73
74#define MEMTAG 0x5aa5
75
76#define MALLOC_TYPE 1
77#define REALLOC_TYPE 2
78#define STRDUP_TYPE 3
79
80typedef struct memnod {
81 unsigned int mh_tag;
82 unsigned int mh_type;
83 unsigned long mh_number;
84 size_t mh_size;
85#ifdef MEM_LIST
86 struct memnod *mh_next;
87 struct memnod *mh_prev;
88#endif
89 const char *mh_file;
90 unsigned int mh_line;
91} MEMHDR;
92
93
94#ifdef SUN4
95#define ALIGN_SIZE 16
96#else
97#define ALIGN_SIZE sizeof(double)
98#endif
99#define HDR_SIZE sizeof(MEMHDR)
100#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
101 / ALIGN_SIZE ) * ALIGN_SIZE)
102
103
104#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
105#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
106
107
108static unsigned long debugMemSize = 0;
109static unsigned long debugMaxMemSize = 0;
110static int block=0;
Daniel Veillardb44025c2001-10-11 22:55:55 +0000111static int xmlMemStopAtBlock = 0;
112static void *xmlMemTraceBlockAt = NULL;
113static int xmlMemInitialized = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000114#ifdef MEM_LIST
115static MEMHDR *memlist = NULL;
116#endif
117
Daniel Veillard01c13b52002-12-10 15:19:08 +0000118static void debugmem_tag_error(void *addr);
Owen Taylor3473f882001-02-23 17:55:21 +0000119#ifdef MEM_LIST
Daniel Veillard01c13b52002-12-10 15:19:08 +0000120static void debugmem_list_add(MEMHDR *);
121static void debugmem_list_delete(MEMHDR *);
Owen Taylor3473f882001-02-23 17:55:21 +0000122#endif
123#define Mem_Tag_Err(a) debugmem_tag_error(a);
124
125#ifndef TEST_POINT
126#define TEST_POINT
127#endif
128
129/**
130 * xmlMallocBreakpoint:
131 *
132 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
133 * number reaches the specified value this function is called. One need to add a breakpoint
134 * to it to get the context in which the given block is allocated.
135 */
136
137void
138xmlMallocBreakpoint(void) {
139 xmlGenericError(xmlGenericErrorContext,
140 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
141}
142
143/**
144 * xmlMallocLoc:
145 * @size: an int specifying the size in byte to allocate.
146 * @file: the file name or NULL
147 * @line: the line number
148 *
149 * a malloc() equivalent, with logging of the allocation info.
150 *
151 * Returns a pointer to the allocated area or NULL in case of lack of memory.
152 */
153
154void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000155xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000156{
157 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000158 void *ret;
Owen Taylor3473f882001-02-23 17:55:21 +0000159
160 if (!xmlMemInitialized) xmlInitMemory();
161#ifdef DEBUG_MEMORY
162 xmlGenericError(xmlGenericErrorContext,
163 "Malloc(%d)\n",size);
164#endif
165
166 TEST_POINT
167
168 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
169
170 if (!p) {
171 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000172 "xmlMallocLoc : Out of free space\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000173 xmlMemoryDump();
174 return(NULL);
175 }
176 p->mh_tag = MEMTAG;
177 p->mh_number = ++block;
178 p->mh_size = size;
179 p->mh_type = MALLOC_TYPE;
180 p->mh_file = file;
181 p->mh_line = line;
182 debugMemSize += size;
183 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
184#ifdef MEM_LIST
185 debugmem_list_add(p);
186#endif
187
188#ifdef DEBUG_MEMORY
189 xmlGenericError(xmlGenericErrorContext,
190 "Malloc(%d) Ok\n",size);
191#endif
192
193 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
194
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000195 ret = HDR_2_CLIENT(p);
196
197 if (xmlMemTraceBlockAt == ret) {
198 xmlGenericError(xmlGenericErrorContext,
199 "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
200 xmlMallocBreakpoint();
201 }
202
Owen Taylor3473f882001-02-23 17:55:21 +0000203 TEST_POINT
204
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000205 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000206}
207
208/**
209 * xmlMemMalloc:
210 * @size: an int specifying the size in byte to allocate.
211 *
212 * a malloc() equivalent, with logging of the allocation info.
213 *
214 * Returns a pointer to the allocated area or NULL in case of lack of memory.
215 */
216
217void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000218xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000219{
220 return(xmlMallocLoc(size, "none", 0));
221}
222
223/**
224 * xmlReallocLoc:
225 * @ptr: the initial memory block pointer
226 * @size: an int specifying the size in byte to allocate.
227 * @file: the file name or NULL
228 * @line: the line number
229 *
230 * a realloc() equivalent, with logging of the allocation info.
231 *
232 * Returns a pointer to the allocated area or NULL in case of lack of memory.
233 */
234
235void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000236xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000237{
238 MEMHDR *p;
239 unsigned long number;
240
241 if (!xmlMemInitialized) xmlInitMemory();
242 TEST_POINT
243
244 p = CLIENT_2_HDR(ptr);
245 number = p->mh_number;
246 if (p->mh_tag != MEMTAG) {
247 Mem_Tag_Err(p);
248 goto error;
249 }
250 p->mh_tag = ~MEMTAG;
251 debugMemSize -= p->mh_size;
252#ifdef MEM_LIST
253 debugmem_list_delete(p);
254#endif
255
256 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
257 if (!p) {
258 goto error;
259 }
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000260 if (xmlMemTraceBlockAt == ptr) {
261 xmlGenericError(xmlGenericErrorContext,
262 "%p : Realloced(%d -> %d) Ok\n",
263 xmlMemTraceBlockAt, p->mh_size, size);
264 xmlMallocBreakpoint();
265 }
Owen Taylor3473f882001-02-23 17:55:21 +0000266 p->mh_tag = MEMTAG;
267 p->mh_number = number;
268 p->mh_type = REALLOC_TYPE;
269 p->mh_size = size;
270 p->mh_file = file;
271 p->mh_line = line;
272 debugMemSize += size;
273 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
274#ifdef MEM_LIST
275 debugmem_list_add(p);
276#endif
277
278 TEST_POINT
279
280 return(HDR_2_CLIENT(p));
281
282error:
283 return(NULL);
284}
285
286/**
287 * xmlMemRealloc:
288 * @ptr: the initial memory block pointer
289 * @size: an int specifying the size in byte to allocate.
290 *
291 * a realloc() equivalent, with logging of the allocation info.
292 *
293 * Returns a pointer to the allocated area or NULL in case of lack of memory.
294 */
295
296void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000297xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000298 return(xmlReallocLoc(ptr, size, "none", 0));
299}
300
301/**
302 * xmlMemFree:
303 * @ptr: the memory block pointer
304 *
305 * a free() equivalent, with error checking.
306 */
307void
308xmlMemFree(void *ptr)
309{
310 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000311 char *target;
Owen Taylor3473f882001-02-23 17:55:21 +0000312
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000313 if (ptr == (void *) -1) {
314 xmlGenericError(xmlGenericErrorContext,
315 "trying to free pointer from freed area\n");
316 goto error;
317 }
318
319 if (xmlMemTraceBlockAt == ptr) {
320 xmlGenericError(xmlGenericErrorContext,
321 "%p : Freed()\n", xmlMemTraceBlockAt);
322 xmlMallocBreakpoint();
323 }
324
Owen Taylor3473f882001-02-23 17:55:21 +0000325 TEST_POINT
326
Daniel Veillard92ad2102001-03-27 12:47:33 +0000327 target = (char *) ptr;
328
Owen Taylor3473f882001-02-23 17:55:21 +0000329 p = CLIENT_2_HDR(ptr);
330 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000331 Mem_Tag_Err(p);
332 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000333 }
334 p->mh_tag = ~MEMTAG;
335 debugMemSize -= p->mh_size;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000336 memset(target, -1, p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000337
338#ifdef MEM_LIST
339 debugmem_list_delete(p);
340#endif
341 free(p);
342
343 TEST_POINT
344
345 return;
346
347error:
348 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000349 "xmlMemFree(%lX) error\n", (unsigned long) ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000350 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000351 return;
352}
353
354/**
355 * xmlMemStrdupLoc:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000356 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000357 * @file: the file name or NULL
358 * @line: the line number
359 *
360 * a strdup() equivalent, with logging of the allocation info.
361 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000362 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000363 */
364
365char *
366xmlMemStrdupLoc(const char *str, const char *file, int line)
367{
368 char *s;
369 size_t size = strlen(str) + 1;
370 MEMHDR *p;
371
372 if (!xmlMemInitialized) xmlInitMemory();
373 TEST_POINT
374
375 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
376 if (!p) {
377 goto error;
378 }
379 p->mh_tag = MEMTAG;
380 p->mh_number = ++block;
381 p->mh_size = size;
382 p->mh_type = STRDUP_TYPE;
383 p->mh_file = file;
384 p->mh_line = line;
385 debugMemSize += size;
386 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
387#ifdef MEM_LIST
388 debugmem_list_add(p);
389#endif
390 s = (char *) HDR_2_CLIENT(p);
391
392 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
393
394 if (s != NULL)
395 strcpy(s,str);
396 else
397 goto error;
398
399 TEST_POINT
400
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000401 if (xmlMemTraceBlockAt == s) {
402 xmlGenericError(xmlGenericErrorContext,
403 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
404 xmlMallocBreakpoint();
405 }
406
Owen Taylor3473f882001-02-23 17:55:21 +0000407 return(s);
408
409error:
410 return(NULL);
411}
412
413/**
414 * xmlMemoryStrdup:
Daniel Veillard01c13b52002-12-10 15:19:08 +0000415 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000416 *
417 * a strdup() equivalent, with logging of the allocation info.
418 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000419 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000420 */
421
422char *
423xmlMemoryStrdup(const char *str) {
424 return(xmlMemStrdupLoc(str, "none", 0));
425}
426
427/**
428 * xmlMemUsed:
429 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +0000430 * Provides the amount of memory currently allocated
Owen Taylor3473f882001-02-23 17:55:21 +0000431 *
432 * Returns an int representing the amount of memory allocated.
433 */
434
435int
436xmlMemUsed(void) {
437 return(debugMemSize);
438}
439
440#ifdef MEM_LIST
441/**
442 * xmlMemContentShow:
443 * @fp: a FILE descriptor used as the output file
444 * @p: a memory block header
445 *
446 * tries to show some content from the memory block
447 */
448
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000449static void
Owen Taylor3473f882001-02-23 17:55:21 +0000450xmlMemContentShow(FILE *fp, MEMHDR *p)
451{
452 int i,j,len = p->mh_size;
453 const char *buf = (const char *) HDR_2_CLIENT(p);
454
455 if (p == NULL) {
456 fprintf(fp, " NULL");
457 return;
458 }
459
460 for (i = 0;i < len;i++) {
461 if (buf[i] == 0) break;
Daniel Veillard9f28f302002-02-15 20:48:08 +0000462 if (!isprint((unsigned char) buf[i])) break;
Owen Taylor3473f882001-02-23 17:55:21 +0000463 }
464 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
465 if (len >= 4) {
466 MEMHDR *q;
467 void *cur;
468
469 for (j = 0;j < len -3;j += 4) {
470 cur = *((void **) &buf[j]);
471 q = CLIENT_2_HDR(cur);
472 p = memlist;
473 while (p != NULL) {
474 if (p == q) break;
475 p = p->mh_next;
476 }
477 if ((p != NULL) && (p == q)) {
478 fprintf(fp, " pointer to #%lu at index %d",
479 p->mh_number, j);
480 return;
481 }
482 }
483 }
484 } else if ((i == 0) && (buf[i] == 0)) {
485 fprintf(fp," null");
486 } else {
487 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
488 else {
489 fprintf(fp," [");
490 for (j = 0;j < i;j++)
491 fprintf(fp,"%c", buf[j]);
492 fprintf(fp,"]");
493 }
494 }
495}
496#endif
497
498/**
499 * xmlMemShow:
500 * @fp: a FILE descriptor used as the output file
501 * @nr: number of entries to dump
502 *
503 * show a show display of the memory allocated, and dump
504 * the @nr last allocated areas which were not freed
505 */
506
507void
508xmlMemShow(FILE *fp, int nr)
509{
510#ifdef MEM_LIST
511 MEMHDR *p;
512#endif
513
514 if (fp != NULL)
515 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
516 debugMemSize, debugMaxMemSize);
517#ifdef MEM_LIST
518 if (nr > 0) {
519 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
520 p = memlist;
521 while ((p) && nr > 0) {
Daniel Veillard144024e2002-02-13 21:14:46 +0000522 fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000523 switch (p->mh_type) {
524 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
525 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
526 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
527 default:fprintf(fp," ??? in ");break;
528 }
529 if (p->mh_file != NULL)
530 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
531 if (p->mh_tag != MEMTAG)
532 fprintf(fp," INVALID");
533 xmlMemContentShow(fp, p);
534 fprintf(fp,"\n");
535 nr--;
536 p = p->mh_next;
537 }
538 }
539#endif /* MEM_LIST */
540}
541
542/**
543 * xmlMemDisplay:
544 * @fp: a FILE descriptor used as the output file, if NULL, the result is
545 * written to the file .memorylist
546 *
547 * show in-extenso the memory blocks allocated
548 */
549
550void
551xmlMemDisplay(FILE *fp)
552{
553#ifdef MEM_LIST
554 MEMHDR *p;
Daniel Veillard144024e2002-02-13 21:14:46 +0000555 unsigned idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000556 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000557#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
558 time_t currentTime;
559 char buf[500];
560 struct tm * tstruct;
561
562 currentTime = time(NULL);
563 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000564 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000565 fprintf(fp," %s\n\n", buf);
566#endif
567
568
569 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
570 debugMemSize, debugMaxMemSize);
571 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
572 idx = 0;
573 p = memlist;
574 while (p) {
Daniel Veillard144024e2002-02-13 21:14:46 +0000575 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
576 (unsigned long)p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000577 switch (p->mh_type) {
578 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
579 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
580 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
581 default:fprintf(fp," ??? in ");break;
582 }
583 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
584 if (p->mh_tag != MEMTAG)
585 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000586 nb++;
587 if (nb < 100)
588 xmlMemContentShow(fp, p);
589 else
590 fprintf(fp," skip");
591
Owen Taylor3473f882001-02-23 17:55:21 +0000592 fprintf(fp,"\n");
593 p = p->mh_next;
594 }
595#else
596 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
597#endif
598}
599
600#ifdef MEM_LIST
601
Daniel Veillard01c13b52002-12-10 15:19:08 +0000602static void debugmem_list_add(MEMHDR *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000603{
604 p->mh_next = memlist;
605 p->mh_prev = NULL;
606 if (memlist) memlist->mh_prev = p;
607 memlist = p;
608#ifdef MEM_LIST_DEBUG
609 if (stderr)
610 Mem_Display(stderr);
611#endif
612}
613
Daniel Veillard01c13b52002-12-10 15:19:08 +0000614static void debugmem_list_delete(MEMHDR *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000615{
616 if (p->mh_next)
617 p->mh_next->mh_prev = p->mh_prev;
618 if (p->mh_prev)
619 p->mh_prev->mh_next = p->mh_next;
620 else memlist = p->mh_next;
621#ifdef MEM_LIST_DEBUG
622 if (stderr)
623 Mem_Display(stderr);
624#endif
625}
626
627#endif
628
629/*
Daniel Veillard01c13b52002-12-10 15:19:08 +0000630 * debugmem_tag_error:
631 *
632 * internal error function.
Owen Taylor3473f882001-02-23 17:55:21 +0000633 */
634
Daniel Veillard01c13b52002-12-10 15:19:08 +0000635static void debugmem_tag_error(void *p)
Owen Taylor3473f882001-02-23 17:55:21 +0000636{
637 xmlGenericError(xmlGenericErrorContext,
638 "Memory tag error occurs :%p \n\t bye\n", p);
639#ifdef MEM_LIST
640 if (stderr)
641 xmlMemDisplay(stderr);
642#endif
643}
644
Daniel Veillardb44025c2001-10-11 22:55:55 +0000645static FILE *xmlMemoryDumpFile = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000646
647
648/**
649 * xmlMemoryDump:
650 *
651 * Dump in-extenso the memory blocks allocated to the file .memorylist
652 */
653
654void
655xmlMemoryDump(void)
656{
Owen Taylor3473f882001-02-23 17:55:21 +0000657 FILE *dump;
658
Daniel Veillard5997aca2002-03-18 18:36:20 +0000659 if (debugMaxMemSize == 0)
660 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000661 dump = fopen(".memdump", "w");
Daniel Veillardcd337f02001-11-22 18:20:37 +0000662 if (dump == NULL)
663 xmlMemoryDumpFile = stderr;
Owen Taylor3473f882001-02-23 17:55:21 +0000664 else xmlMemoryDumpFile = dump;
665
666 xmlMemDisplay(xmlMemoryDumpFile);
667
668 if (dump != NULL) fclose(dump);
Owen Taylor3473f882001-02-23 17:55:21 +0000669}
670
671
672/****************************************************************
673 * *
674 * Initialization Routines *
675 * *
676 ****************************************************************/
677
Daniel Veillard01c13b52002-12-10 15:19:08 +0000678static int xmlInitMemoryDone = 0;
679
Owen Taylor3473f882001-02-23 17:55:21 +0000680/**
681 * xmlInitMemory:
682 *
683 * Initialize the memory layer.
684 *
685 * Returns 0 on success
686 */
Owen Taylor3473f882001-02-23 17:55:21 +0000687int
688xmlInitMemory(void)
689{
690 int ret;
691
692#ifdef HAVE_STDLIB_H
693 char *breakpoint;
694#endif
695
696 if (xmlInitMemoryDone) return(-1);
697
698#ifdef HAVE_STDLIB_H
699 breakpoint = getenv("XML_MEM_BREAKPOINT");
700 if (breakpoint != NULL) {
701 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
702 }
703#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000704#ifdef HAVE_STDLIB_H
705 breakpoint = getenv("XML_MEM_TRACE");
706 if (breakpoint != NULL) {
707 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
708 }
709#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000710
711#ifdef DEBUG_MEMORY
712 xmlGenericError(xmlGenericErrorContext,
713 "xmlInitMemory() Ok\n");
714#endif
Daniel Veillardd30be4a2002-03-28 18:25:31 +0000715 xmlMemInitialized = 1;
716 xmlInitMemoryDone = 1;
717
Owen Taylor3473f882001-02-23 17:55:21 +0000718 ret = 0;
719 return(ret);
720}
721
722/**
723 * xmlMemSetup:
724 * @freeFunc: the free() function to use
725 * @mallocFunc: the malloc() function to use
726 * @reallocFunc: the realloc() function to use
727 * @strdupFunc: the strdup() function to use
728 *
729 * Override the default memory access functions with a new set
730 * This has to be called before any other libxml routines !
731 *
732 * Should this be blocked if there was already some allocations
733 * done ?
734 *
735 * Returns 0 on success
736 */
737int
738xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
739 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
740 if (freeFunc == NULL)
741 return(-1);
742 if (mallocFunc == NULL)
743 return(-1);
744 if (reallocFunc == NULL)
745 return(-1);
746 if (strdupFunc == NULL)
747 return(-1);
748 xmlFree = freeFunc;
749 xmlMalloc = mallocFunc;
750 xmlRealloc = reallocFunc;
751 xmlMemStrdup = strdupFunc;
752 return(0);
753}
754
755/**
756 * xmlMemGet:
Daniel Veillarda9b66d02002-12-11 14:23:49 +0000757 * @freeFunc: place to save the free() function in use
758 * @mallocFunc: place to save the malloc() function in use
759 * @reallocFunc: place to save the realloc() function in use
760 * @strdupFunc: place to save the strdup() function in use
Owen Taylor3473f882001-02-23 17:55:21 +0000761 *
Daniel Veillarda9b66d02002-12-11 14:23:49 +0000762 * Provides the memory access functions set currently in use
Owen Taylor3473f882001-02-23 17:55:21 +0000763 *
764 * Returns 0 on success
765 */
766int
767xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
768 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
769 if (freeFunc != NULL) *freeFunc = xmlFree;
770 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
771 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
772 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
773 return(0);
774}
775