blob: 3938a047e6de8e4f514155e73eb62548c2173b7f [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
Bjorn Reese70a9da52001-04-21 16:57:29 +00007#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +00008
Owen Taylor3473f882001-02-23 17:55:21 +00009#include <string.h>
10
11#ifdef HAVE_SYS_TYPES_H
12#include <sys/types.h>
13#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000014
Owen Taylor3473f882001-02-23 17:55:21 +000015#ifdef HAVE_TIME_H
16#include <time.h>
17#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000018
19#ifdef HAVE_STDLIB_H
20#include <stdlib.h>
21#else
Owen Taylor3473f882001-02-23 17:55:21 +000022#ifdef HAVE_MALLOC_H
23#include <malloc.h>
24#endif
Owen Taylor3473f882001-02-23 17:55:21 +000025#endif
Daniel Veillard0ba59232002-02-10 13:20:39 +000026
Owen Taylor3473f882001-02-23 17:55:21 +000027#ifdef HAVE_CTYPE_H
28#include <ctype.h>
29#endif
30
Daniel Veillard70cab352002-02-06 16:06:58 +000031/**
32 * MEM_LIST:
33 *
34 * keep track of all allocated blocks for error reporting
35 * Always build the memory list !
36 */
37#ifndef MEM_LIST
38#define MEM_LIST /* keep a list of all the allocated memory blocks */
39#endif
Owen Taylor3473f882001-02-23 17:55:21 +000040
41#include <libxml/xmlmemory.h>
Daniel Veillardd0463562001-10-13 09:15:48 +000042#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000043#include <libxml/xmlerror.h>
44
Daniel Veillard56a4cb82001-03-24 17:00:36 +000045void xmlMallocBreakpoint(void);
Daniel Veillard8599e702001-07-17 21:38:51 +000046void * xmlMemMalloc(size_t size);
Daniel Veillard8599e702001-07-17 21:38:51 +000047void * xmlMemRealloc(void *ptr,size_t size);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000048void xmlMemFree(void *ptr);
49char * xmlMemoryStrdup(const char *str);
50
51/************************************************************************
52 * *
53 * Macros, variables and associated types *
54 * *
55 ************************************************************************/
56
57
Owen Taylor3473f882001-02-23 17:55:21 +000058#ifdef xmlMalloc
59#undef xmlMalloc
60#endif
61#ifdef xmlRealloc
62#undef xmlRealloc
63#endif
64#ifdef xmlMemStrdup
65#undef xmlMemStrdup
66#endif
67
68
69/*
70 * Each of the blocks allocated begin with a header containing informations
71 */
72
73#define MEMTAG 0x5aa5
74
75#define MALLOC_TYPE 1
76#define REALLOC_TYPE 2
77#define STRDUP_TYPE 3
78
79typedef struct memnod {
80 unsigned int mh_tag;
81 unsigned int mh_type;
82 unsigned long mh_number;
83 size_t mh_size;
84#ifdef MEM_LIST
85 struct memnod *mh_next;
86 struct memnod *mh_prev;
87#endif
88 const char *mh_file;
89 unsigned int mh_line;
90} MEMHDR;
91
92
93#ifdef SUN4
94#define ALIGN_SIZE 16
95#else
96#define ALIGN_SIZE sizeof(double)
97#endif
98#define HDR_SIZE sizeof(MEMHDR)
99#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
100 / ALIGN_SIZE ) * ALIGN_SIZE)
101
102
103#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
104#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
105
106
107static unsigned long debugMemSize = 0;
108static unsigned long debugMaxMemSize = 0;
109static int block=0;
Daniel Veillardb44025c2001-10-11 22:55:55 +0000110static int xmlMemStopAtBlock = 0;
111static void *xmlMemTraceBlockAt = NULL;
112static int xmlMemInitialized = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000113#ifdef MEM_LIST
114static MEMHDR *memlist = NULL;
115#endif
116
117void debugmem_tag_error(void *addr);
118#ifdef MEM_LIST
119void debugmem_list_add(MEMHDR *);
120void debugmem_list_delete(MEMHDR *);
121#endif
122#define Mem_Tag_Err(a) debugmem_tag_error(a);
123
124#ifndef TEST_POINT
125#define TEST_POINT
126#endif
127
128/**
129 * xmlMallocBreakpoint:
130 *
131 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
132 * number reaches the specified value this function is called. One need to add a breakpoint
133 * to it to get the context in which the given block is allocated.
134 */
135
136void
137xmlMallocBreakpoint(void) {
138 xmlGenericError(xmlGenericErrorContext,
139 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
140}
141
142/**
143 * xmlMallocLoc:
144 * @size: an int specifying the size in byte to allocate.
145 * @file: the file name or NULL
146 * @line: the line number
147 *
148 * a malloc() equivalent, with logging of the allocation info.
149 *
150 * Returns a pointer to the allocated area or NULL in case of lack of memory.
151 */
152
153void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000154xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000155{
156 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000157 void *ret;
Owen Taylor3473f882001-02-23 17:55:21 +0000158
159 if (!xmlMemInitialized) xmlInitMemory();
160#ifdef DEBUG_MEMORY
161 xmlGenericError(xmlGenericErrorContext,
162 "Malloc(%d)\n",size);
163#endif
164
165 TEST_POINT
166
167 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
168
169 if (!p) {
170 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000171 "xmlMallocLoc : Out of free space\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000172 xmlMemoryDump();
173 return(NULL);
174 }
175 p->mh_tag = MEMTAG;
176 p->mh_number = ++block;
177 p->mh_size = size;
178 p->mh_type = MALLOC_TYPE;
179 p->mh_file = file;
180 p->mh_line = line;
181 debugMemSize += size;
182 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
183#ifdef MEM_LIST
184 debugmem_list_add(p);
185#endif
186
187#ifdef DEBUG_MEMORY
188 xmlGenericError(xmlGenericErrorContext,
189 "Malloc(%d) Ok\n",size);
190#endif
191
192 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
193
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000194 ret = HDR_2_CLIENT(p);
195
196 if (xmlMemTraceBlockAt == ret) {
197 xmlGenericError(xmlGenericErrorContext,
198 "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
199 xmlMallocBreakpoint();
200 }
201
Owen Taylor3473f882001-02-23 17:55:21 +0000202 TEST_POINT
203
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000204 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000205}
206
207/**
208 * xmlMemMalloc:
209 * @size: an int specifying the size in byte to allocate.
210 *
211 * a malloc() equivalent, with logging of the allocation info.
212 *
213 * Returns a pointer to the allocated area or NULL in case of lack of memory.
214 */
215
216void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000217xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000218{
219 return(xmlMallocLoc(size, "none", 0));
220}
221
222/**
223 * xmlReallocLoc:
224 * @ptr: the initial memory block pointer
225 * @size: an int specifying the size in byte to allocate.
226 * @file: the file name or NULL
227 * @line: the line number
228 *
229 * a realloc() equivalent, with logging of the allocation info.
230 *
231 * Returns a pointer to the allocated area or NULL in case of lack of memory.
232 */
233
234void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000235xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000236{
237 MEMHDR *p;
238 unsigned long number;
239
240 if (!xmlMemInitialized) xmlInitMemory();
241 TEST_POINT
242
243 p = CLIENT_2_HDR(ptr);
244 number = p->mh_number;
245 if (p->mh_tag != MEMTAG) {
246 Mem_Tag_Err(p);
247 goto error;
248 }
249 p->mh_tag = ~MEMTAG;
250 debugMemSize -= p->mh_size;
251#ifdef MEM_LIST
252 debugmem_list_delete(p);
253#endif
254
255 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
256 if (!p) {
257 goto error;
258 }
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000259 if (xmlMemTraceBlockAt == ptr) {
260 xmlGenericError(xmlGenericErrorContext,
261 "%p : Realloced(%d -> %d) Ok\n",
262 xmlMemTraceBlockAt, p->mh_size, size);
263 xmlMallocBreakpoint();
264 }
Owen Taylor3473f882001-02-23 17:55:21 +0000265 p->mh_tag = MEMTAG;
266 p->mh_number = number;
267 p->mh_type = REALLOC_TYPE;
268 p->mh_size = size;
269 p->mh_file = file;
270 p->mh_line = line;
271 debugMemSize += size;
272 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
273#ifdef MEM_LIST
274 debugmem_list_add(p);
275#endif
276
277 TEST_POINT
278
279 return(HDR_2_CLIENT(p));
280
281error:
282 return(NULL);
283}
284
285/**
286 * xmlMemRealloc:
287 * @ptr: the initial memory block pointer
288 * @size: an int specifying the size in byte to allocate.
289 *
290 * a realloc() equivalent, with logging of the allocation info.
291 *
292 * Returns a pointer to the allocated area or NULL in case of lack of memory.
293 */
294
295void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000296xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000297 return(xmlReallocLoc(ptr, size, "none", 0));
298}
299
300/**
301 * xmlMemFree:
302 * @ptr: the memory block pointer
303 *
304 * a free() equivalent, with error checking.
305 */
306void
307xmlMemFree(void *ptr)
308{
309 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000310 char *target;
Owen Taylor3473f882001-02-23 17:55:21 +0000311
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000312 if (ptr == (void *) -1) {
313 xmlGenericError(xmlGenericErrorContext,
314 "trying to free pointer from freed area\n");
315 goto error;
316 }
317
318 if (xmlMemTraceBlockAt == ptr) {
319 xmlGenericError(xmlGenericErrorContext,
320 "%p : Freed()\n", xmlMemTraceBlockAt);
321 xmlMallocBreakpoint();
322 }
323
Owen Taylor3473f882001-02-23 17:55:21 +0000324 TEST_POINT
325
Daniel Veillard92ad2102001-03-27 12:47:33 +0000326 target = (char *) ptr;
327
Owen Taylor3473f882001-02-23 17:55:21 +0000328 p = CLIENT_2_HDR(ptr);
329 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000330 Mem_Tag_Err(p);
331 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000332 }
333 p->mh_tag = ~MEMTAG;
334 debugMemSize -= p->mh_size;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000335 memset(target, -1, p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000336
337#ifdef MEM_LIST
338 debugmem_list_delete(p);
339#endif
340 free(p);
341
342 TEST_POINT
343
344 return;
345
346error:
347 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000348 "xmlMemFree(%lX) error\n", (unsigned long) ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000349 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000350 return;
351}
352
353/**
354 * xmlMemStrdupLoc:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000355 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000356 * @file: the file name or NULL
357 * @line: the line number
358 *
359 * a strdup() equivalent, with logging of the allocation info.
360 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000361 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000362 */
363
364char *
365xmlMemStrdupLoc(const char *str, const char *file, int line)
366{
367 char *s;
368 size_t size = strlen(str) + 1;
369 MEMHDR *p;
370
371 if (!xmlMemInitialized) xmlInitMemory();
372 TEST_POINT
373
374 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
375 if (!p) {
376 goto error;
377 }
378 p->mh_tag = MEMTAG;
379 p->mh_number = ++block;
380 p->mh_size = size;
381 p->mh_type = STRDUP_TYPE;
382 p->mh_file = file;
383 p->mh_line = line;
384 debugMemSize += size;
385 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
386#ifdef MEM_LIST
387 debugmem_list_add(p);
388#endif
389 s = (char *) HDR_2_CLIENT(p);
390
391 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
392
393 if (s != NULL)
394 strcpy(s,str);
395 else
396 goto error;
397
398 TEST_POINT
399
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000400 if (xmlMemTraceBlockAt == s) {
401 xmlGenericError(xmlGenericErrorContext,
402 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
403 xmlMallocBreakpoint();
404 }
405
Owen Taylor3473f882001-02-23 17:55:21 +0000406 return(s);
407
408error:
409 return(NULL);
410}
411
412/**
413 * xmlMemoryStrdup:
414 * @ptr: the initial string pointer
415 *
416 * a strdup() equivalent, with logging of the allocation info.
417 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000418 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000419 */
420
421char *
422xmlMemoryStrdup(const char *str) {
423 return(xmlMemStrdupLoc(str, "none", 0));
424}
425
426/**
427 * xmlMemUsed:
428 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000429 * returns the amount of memory currently allocated
Owen Taylor3473f882001-02-23 17:55:21 +0000430 *
431 * Returns an int representing the amount of memory allocated.
432 */
433
434int
435xmlMemUsed(void) {
436 return(debugMemSize);
437}
438
439#ifdef MEM_LIST
440/**
441 * xmlMemContentShow:
442 * @fp: a FILE descriptor used as the output file
443 * @p: a memory block header
444 *
445 * tries to show some content from the memory block
446 */
447
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000448static void
Owen Taylor3473f882001-02-23 17:55:21 +0000449xmlMemContentShow(FILE *fp, MEMHDR *p)
450{
451 int i,j,len = p->mh_size;
452 const char *buf = (const char *) HDR_2_CLIENT(p);
453
454 if (p == NULL) {
455 fprintf(fp, " NULL");
456 return;
457 }
458
459 for (i = 0;i < len;i++) {
460 if (buf[i] == 0) break;
Daniel Veillard9f28f302002-02-15 20:48:08 +0000461 if (!isprint((unsigned char) buf[i])) break;
Owen Taylor3473f882001-02-23 17:55:21 +0000462 }
463 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
464 if (len >= 4) {
465 MEMHDR *q;
466 void *cur;
467
468 for (j = 0;j < len -3;j += 4) {
469 cur = *((void **) &buf[j]);
470 q = CLIENT_2_HDR(cur);
471 p = memlist;
472 while (p != NULL) {
473 if (p == q) break;
474 p = p->mh_next;
475 }
476 if ((p != NULL) && (p == q)) {
477 fprintf(fp, " pointer to #%lu at index %d",
478 p->mh_number, j);
479 return;
480 }
481 }
482 }
483 } else if ((i == 0) && (buf[i] == 0)) {
484 fprintf(fp," null");
485 } else {
486 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
487 else {
488 fprintf(fp," [");
489 for (j = 0;j < i;j++)
490 fprintf(fp,"%c", buf[j]);
491 fprintf(fp,"]");
492 }
493 }
494}
495#endif
496
497/**
498 * xmlMemShow:
499 * @fp: a FILE descriptor used as the output file
500 * @nr: number of entries to dump
501 *
502 * show a show display of the memory allocated, and dump
503 * the @nr last allocated areas which were not freed
504 */
505
506void
507xmlMemShow(FILE *fp, int nr)
508{
509#ifdef MEM_LIST
510 MEMHDR *p;
511#endif
512
513 if (fp != NULL)
514 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
515 debugMemSize, debugMaxMemSize);
516#ifdef MEM_LIST
517 if (nr > 0) {
518 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
519 p = memlist;
520 while ((p) && nr > 0) {
Daniel Veillard144024e2002-02-13 21:14:46 +0000521 fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000522 switch (p->mh_type) {
523 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
524 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
525 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
526 default:fprintf(fp," ??? in ");break;
527 }
528 if (p->mh_file != NULL)
529 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
530 if (p->mh_tag != MEMTAG)
531 fprintf(fp," INVALID");
532 xmlMemContentShow(fp, p);
533 fprintf(fp,"\n");
534 nr--;
535 p = p->mh_next;
536 }
537 }
538#endif /* MEM_LIST */
539}
540
541/**
542 * xmlMemDisplay:
543 * @fp: a FILE descriptor used as the output file, if NULL, the result is
544 * written to the file .memorylist
545 *
546 * show in-extenso the memory blocks allocated
547 */
548
549void
550xmlMemDisplay(FILE *fp)
551{
552#ifdef MEM_LIST
553 MEMHDR *p;
Daniel Veillard144024e2002-02-13 21:14:46 +0000554 unsigned idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000555 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000556#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
557 time_t currentTime;
558 char buf[500];
559 struct tm * tstruct;
560
561 currentTime = time(NULL);
562 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000563 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000564 fprintf(fp," %s\n\n", buf);
565#endif
566
567
568 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
569 debugMemSize, debugMaxMemSize);
570 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
571 idx = 0;
572 p = memlist;
573 while (p) {
Daniel Veillard144024e2002-02-13 21:14:46 +0000574 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
575 (unsigned long)p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000576 switch (p->mh_type) {
577 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
578 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
579 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
580 default:fprintf(fp," ??? in ");break;
581 }
582 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
583 if (p->mh_tag != MEMTAG)
584 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000585 nb++;
586 if (nb < 100)
587 xmlMemContentShow(fp, p);
588 else
589 fprintf(fp," skip");
590
Owen Taylor3473f882001-02-23 17:55:21 +0000591 fprintf(fp,"\n");
592 p = p->mh_next;
593 }
594#else
595 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
596#endif
597}
598
599#ifdef MEM_LIST
600
601void debugmem_list_add(MEMHDR *p)
602{
603 p->mh_next = memlist;
604 p->mh_prev = NULL;
605 if (memlist) memlist->mh_prev = p;
606 memlist = p;
607#ifdef MEM_LIST_DEBUG
608 if (stderr)
609 Mem_Display(stderr);
610#endif
611}
612
613void debugmem_list_delete(MEMHDR *p)
614{
615 if (p->mh_next)
616 p->mh_next->mh_prev = p->mh_prev;
617 if (p->mh_prev)
618 p->mh_prev->mh_next = p->mh_next;
619 else memlist = p->mh_next;
620#ifdef MEM_LIST_DEBUG
621 if (stderr)
622 Mem_Display(stderr);
623#endif
624}
625
626#endif
627
628/*
629 * debugmem_tag_error : internal error function.
630 */
631
632void debugmem_tag_error(void *p)
633{
634 xmlGenericError(xmlGenericErrorContext,
635 "Memory tag error occurs :%p \n\t bye\n", p);
636#ifdef MEM_LIST
637 if (stderr)
638 xmlMemDisplay(stderr);
639#endif
640}
641
Daniel Veillardb44025c2001-10-11 22:55:55 +0000642static FILE *xmlMemoryDumpFile = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000643
644
645/**
646 * xmlMemoryDump:
647 *
648 * Dump in-extenso the memory blocks allocated to the file .memorylist
649 */
650
651void
652xmlMemoryDump(void)
653{
Owen Taylor3473f882001-02-23 17:55:21 +0000654 FILE *dump;
655
656 dump = fopen(".memdump", "w");
Daniel Veillardcd337f02001-11-22 18:20:37 +0000657 if (dump == NULL)
658 xmlMemoryDumpFile = stderr;
Owen Taylor3473f882001-02-23 17:55:21 +0000659 else xmlMemoryDumpFile = dump;
660
661 xmlMemDisplay(xmlMemoryDumpFile);
662
663 if (dump != NULL) fclose(dump);
Owen Taylor3473f882001-02-23 17:55:21 +0000664}
665
666
667/****************************************************************
668 * *
669 * Initialization Routines *
670 * *
671 ****************************************************************/
672
Owen Taylor3473f882001-02-23 17:55:21 +0000673/**
674 * xmlInitMemory:
675 *
676 * Initialize the memory layer.
677 *
678 * Returns 0 on success
679 */
680
681static int xmlInitMemoryDone = 0;
682
683int
684xmlInitMemory(void)
685{
686 int ret;
687
688#ifdef HAVE_STDLIB_H
689 char *breakpoint;
690#endif
691
692 if (xmlInitMemoryDone) return(-1);
693
694#ifdef HAVE_STDLIB_H
695 breakpoint = getenv("XML_MEM_BREAKPOINT");
696 if (breakpoint != NULL) {
697 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
698 }
699#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000700#ifdef HAVE_STDLIB_H
701 breakpoint = getenv("XML_MEM_TRACE");
702 if (breakpoint != NULL) {
703 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
704 }
705#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000706
707#ifdef DEBUG_MEMORY
708 xmlGenericError(xmlGenericErrorContext,
709 "xmlInitMemory() Ok\n");
710#endif
711 ret = 0;
712 return(ret);
713}
714
715/**
716 * xmlMemSetup:
717 * @freeFunc: the free() function to use
718 * @mallocFunc: the malloc() function to use
719 * @reallocFunc: the realloc() function to use
720 * @strdupFunc: the strdup() function to use
721 *
722 * Override the default memory access functions with a new set
723 * This has to be called before any other libxml routines !
724 *
725 * Should this be blocked if there was already some allocations
726 * done ?
727 *
728 * Returns 0 on success
729 */
730int
731xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
732 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
733 if (freeFunc == NULL)
734 return(-1);
735 if (mallocFunc == NULL)
736 return(-1);
737 if (reallocFunc == NULL)
738 return(-1);
739 if (strdupFunc == NULL)
740 return(-1);
741 xmlFree = freeFunc;
742 xmlMalloc = mallocFunc;
743 xmlRealloc = reallocFunc;
744 xmlMemStrdup = strdupFunc;
745 return(0);
746}
747
748/**
749 * xmlMemGet:
750 * @freeFunc: the free() function in use
751 * @mallocFunc: the malloc() function in use
752 * @reallocFunc: the realloc() function in use
753 * @strdupFunc: the strdup() function in use
754 *
755 * Return the memory access functions set currently in use
756 *
757 * Returns 0 on success
758 */
759int
760xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
761 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
762 if (freeFunc != NULL) *freeFunc = xmlFree;
763 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
764 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
765 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
766 return(0);
767}
768