VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/xmlmemory.c

Last change on this file was 104200, checked in by vboxsync, 6 weeks ago

libxml2-2.12.6: Make it build for linux​ bugref:10640

  • Property svn:eol-style set to native
File size: 23.5 KB
Line 
1/*
2 * xmlmemory.c: libxml memory allocator wrapper.
3 *
4 * daniel@veillard.com
5 */
6
7#define IN_LIBXML
8#include "libxml.h"
9
10#include <string.h>
11#include <stdlib.h>
12#include <ctype.h>
13#include <time.h>
14
15/**
16 * MEM_LIST:
17 *
18 * keep track of all allocated blocks for error reporting
19 * Always build the memory list !
20 */
21#ifdef DEBUG_MEMORY_LOCATION
22 #ifndef MEM_LIST
23 #define MEM_LIST /* keep a list of all the allocated memory blocks */
24 #endif
25#endif
26
27#include <libxml/xmlmemory.h>
28#include <libxml/xmlerror.h>
29#include <libxml/parser.h>
30#include <libxml/threads.h>
31
32#include "private/memory.h"
33#include "private/threads.h"
34
35static int xmlMemInitialized = 0;
36static unsigned long debugMemSize = 0;
37static unsigned long debugMemBlocks = 0;
38static unsigned long debugMaxMemSize = 0;
39static xmlMutex xmlMemMutex;
40
41void xmlMallocBreakpoint(void);
42
43/************************************************************************
44 * *
45 * Macros, variables and associated types *
46 * *
47 ************************************************************************/
48
49#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
50 #ifdef xmlMalloc
51 #undef xmlMalloc
52 #endif
53
54 #ifdef xmlRealloc
55 #undef xmlRealloc
56 #endif
57
58 #ifdef xmlMemStrdup
59 #undef xmlMemStrdup
60 #endif
61#endif
62
63/*
64 * Each of the blocks allocated begin with a header containing information
65 */
66
67#define MEMTAG 0x5aa5U
68
69#define MALLOC_TYPE 1
70#define REALLOC_TYPE 2
71#define STRDUP_TYPE 3
72#define MALLOC_ATOMIC_TYPE 4
73#define REALLOC_ATOMIC_TYPE 5
74
75typedef struct memnod {
76 unsigned int mh_tag;
77 unsigned int mh_type;
78 unsigned long mh_number;
79 size_t mh_size;
80#ifdef MEM_LIST
81 struct memnod *mh_next;
82 struct memnod *mh_prev;
83#endif
84 const char *mh_file;
85 unsigned int mh_line;
86} MEMHDR;
87
88
89#ifdef SUN4
90#define ALIGN_SIZE 16
91#else
92#define ALIGN_SIZE sizeof(double)
93#endif
94
95#define HDR_SIZE sizeof(MEMHDR)
96#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
97 / ALIGN_SIZE ) * ALIGN_SIZE)
98
99#define MAX_SIZE_T ((size_t)-1)
100
101#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
102#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
103
104
105static unsigned int block=0;
106static unsigned int xmlMemStopAtBlock = 0;
107static void *xmlMemTraceBlockAt = NULL;
108#ifdef MEM_LIST
109static MEMHDR *memlist = NULL;
110#endif
111
112static void debugmem_tag_error(void *addr);
113#ifdef MEM_LIST
114static void debugmem_list_add(MEMHDR *);
115static void debugmem_list_delete(MEMHDR *);
116#endif
117#define Mem_Tag_Err(a) debugmem_tag_error(a);
118
119#ifndef TEST_POINT
120#define TEST_POINT
121#endif
122
123/**
124 * xmlMallocBreakpoint:
125 *
126 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
127 * number reaches the specified value this function is called. One need to add a breakpoint
128 * to it to get the context in which the given block is allocated.
129 */
130
131void
132xmlMallocBreakpoint(void) {
133 xmlGenericError(xmlGenericErrorContext,
134 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
135}
136
137/**
138 * xmlMallocLoc:
139 * @size: an int specifying the size in byte to allocate.
140 * @file: the file name or NULL
141 * @line: the line number
142 *
143 * a malloc() equivalent, with logging of the allocation info.
144 *
145 * Returns a pointer to the allocated area or NULL in case of lack of memory.
146 */
147
148void *
149xmlMallocLoc(size_t size, const char * file, int line)
150{
151 MEMHDR *p;
152 void *ret;
153
154 xmlInitParser();
155
156 TEST_POINT
157
158 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
159 xmlGenericError(xmlGenericErrorContext,
160 "xmlMallocLoc : Unsigned overflow\n");
161 return(NULL);
162 }
163
164 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
165
166 if (!p) {
167 xmlGenericError(xmlGenericErrorContext,
168 "xmlMallocLoc : Out of free space\n");
169 return(NULL);
170 }
171 p->mh_tag = MEMTAG;
172 p->mh_size = size;
173 p->mh_type = MALLOC_TYPE;
174 p->mh_file = file;
175 p->mh_line = line;
176 xmlMutexLock(&xmlMemMutex);
177 p->mh_number = ++block;
178 debugMemSize += size;
179 debugMemBlocks++;
180 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
181#ifdef MEM_LIST
182 debugmem_list_add(p);
183#endif
184 xmlMutexUnlock(&xmlMemMutex);
185
186 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
187
188 ret = HDR_2_CLIENT(p);
189
190 if (xmlMemTraceBlockAt == ret) {
191 xmlGenericError(xmlGenericErrorContext,
192 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
193 (long unsigned)size);
194 xmlMallocBreakpoint();
195 }
196
197 TEST_POINT
198
199 return(ret);
200}
201
202/**
203 * xmlMallocAtomicLoc:
204 * @size: an unsigned int specifying the size in byte to allocate.
205 * @file: the file name or NULL
206 * @line: the line number
207 *
208 * a malloc() equivalent, with logging of the allocation info.
209 *
210 * Returns a pointer to the allocated area or NULL in case of lack of memory.
211 */
212
213void *
214xmlMallocAtomicLoc(size_t size, const char * file, int line)
215{
216 MEMHDR *p;
217 void *ret;
218
219 xmlInitParser();
220
221 TEST_POINT
222
223 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
224 xmlGenericError(xmlGenericErrorContext,
225 "xmlMallocAtomicLoc : Unsigned overflow\n");
226 return(NULL);
227 }
228
229 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
230
231 if (!p) {
232 xmlGenericError(xmlGenericErrorContext,
233 "xmlMallocAtomicLoc : Out of free space\n");
234 return(NULL);
235 }
236 p->mh_tag = MEMTAG;
237 p->mh_size = size;
238 p->mh_type = MALLOC_ATOMIC_TYPE;
239 p->mh_file = file;
240 p->mh_line = line;
241 xmlMutexLock(&xmlMemMutex);
242 p->mh_number = ++block;
243 debugMemSize += size;
244 debugMemBlocks++;
245 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
246#ifdef MEM_LIST
247 debugmem_list_add(p);
248#endif
249 xmlMutexUnlock(&xmlMemMutex);
250
251 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
252
253 ret = HDR_2_CLIENT(p);
254
255 if (xmlMemTraceBlockAt == ret) {
256 xmlGenericError(xmlGenericErrorContext,
257 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
258 (long unsigned)size);
259 xmlMallocBreakpoint();
260 }
261
262 TEST_POINT
263
264 return(ret);
265}
266/**
267 * xmlMemMalloc:
268 * @size: an int specifying the size in byte to allocate.
269 *
270 * a malloc() equivalent, with logging of the allocation info.
271 *
272 * Returns a pointer to the allocated area or NULL in case of lack of memory.
273 */
274
275void *
276xmlMemMalloc(size_t size)
277{
278 return(xmlMallocLoc(size, "none", 0));
279}
280
281/**
282 * xmlReallocLoc:
283 * @ptr: the initial memory block pointer
284 * @size: an int specifying the size in byte to allocate.
285 * @file: the file name or NULL
286 * @line: the line number
287 *
288 * a realloc() equivalent, with logging of the allocation info.
289 *
290 * Returns a pointer to the allocated area or NULL in case of lack of memory.
291 */
292
293void *
294xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
295{
296 MEMHDR *p, *tmp;
297 unsigned long number;
298
299 if (ptr == NULL)
300 return(xmlMallocLoc(size, file, line));
301
302 xmlInitParser();
303 TEST_POINT
304
305 p = CLIENT_2_HDR(ptr);
306 number = p->mh_number;
307 if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
308 if (p->mh_tag != MEMTAG) {
309 Mem_Tag_Err(p);
310 goto error;
311 }
312 p->mh_tag = ~MEMTAG;
313 xmlMutexLock(&xmlMemMutex);
314 debugMemSize -= p->mh_size;
315 debugMemBlocks--;
316#ifdef MEM_LIST
317 debugmem_list_delete(p);
318#endif
319 xmlMutexUnlock(&xmlMemMutex);
320
321 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
322 xmlGenericError(xmlGenericErrorContext,
323 "xmlReallocLoc : Unsigned overflow\n");
324 return(NULL);
325 }
326
327 tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
328 if (!tmp) {
329 free(p);
330 goto error;
331 }
332 p = tmp;
333 if (xmlMemTraceBlockAt == ptr) {
334 xmlGenericError(xmlGenericErrorContext,
335 "%p : Realloced(%lu -> %lu) Ok\n",
336 xmlMemTraceBlockAt, (long unsigned)p->mh_size,
337 (long unsigned)size);
338 xmlMallocBreakpoint();
339 }
340 p->mh_tag = MEMTAG;
341 p->mh_number = number;
342 p->mh_type = REALLOC_TYPE;
343 p->mh_size = size;
344 p->mh_file = file;
345 p->mh_line = line;
346 xmlMutexLock(&xmlMemMutex);
347 debugMemSize += size;
348 debugMemBlocks++;
349 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
350#ifdef MEM_LIST
351 debugmem_list_add(p);
352#endif
353 xmlMutexUnlock(&xmlMemMutex);
354
355 TEST_POINT
356
357 return(HDR_2_CLIENT(p));
358
359error:
360 return(NULL);
361}
362
363/**
364 * xmlMemRealloc:
365 * @ptr: the initial memory block pointer
366 * @size: an int specifying the size in byte to allocate.
367 *
368 * a realloc() equivalent, with logging of the allocation info.
369 *
370 * Returns a pointer to the allocated area or NULL in case of lack of memory.
371 */
372
373void *
374xmlMemRealloc(void *ptr,size_t size) {
375 return(xmlReallocLoc(ptr, size, "none", 0));
376}
377
378/**
379 * xmlMemFree:
380 * @ptr: the memory block pointer
381 *
382 * a free() equivalent, with error checking.
383 */
384void
385xmlMemFree(void *ptr)
386{
387 MEMHDR *p;
388 char *target;
389
390 if (ptr == NULL)
391 return;
392
393 if (ptr == (void *) -1) {
394 xmlGenericError(xmlGenericErrorContext,
395 "trying to free pointer from freed area\n");
396 goto error;
397 }
398
399 if (xmlMemTraceBlockAt == ptr) {
400 xmlGenericError(xmlGenericErrorContext,
401 "%p : Freed()\n", xmlMemTraceBlockAt);
402 xmlMallocBreakpoint();
403 }
404
405 TEST_POINT
406
407 target = (char *) ptr;
408
409 p = CLIENT_2_HDR(ptr);
410 if (p->mh_tag != MEMTAG) {
411 Mem_Tag_Err(p);
412 goto error;
413 }
414 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
415 p->mh_tag = ~MEMTAG;
416 memset(target, -1, p->mh_size);
417 xmlMutexLock(&xmlMemMutex);
418 debugMemSize -= p->mh_size;
419 debugMemBlocks--;
420#ifdef MEM_LIST
421 debugmem_list_delete(p);
422#endif
423 xmlMutexUnlock(&xmlMemMutex);
424
425 free(p);
426
427 TEST_POINT
428
429 return;
430
431error:
432 xmlGenericError(xmlGenericErrorContext,
433 "xmlMemFree(%p) error\n", ptr);
434 xmlMallocBreakpoint();
435 return;
436}
437
438/**
439 * xmlMemStrdupLoc:
440 * @str: the initial string pointer
441 * @file: the file name or NULL
442 * @line: the line number
443 *
444 * a strdup() equivalent, with logging of the allocation info.
445 *
446 * Returns a pointer to the new string or NULL if allocation error occurred.
447 */
448
449char *
450xmlMemStrdupLoc(const char *str, const char *file, int line)
451{
452 char *s;
453 size_t size = strlen(str) + 1;
454 MEMHDR *p;
455
456 xmlInitParser();
457 TEST_POINT
458
459 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
460 xmlGenericError(xmlGenericErrorContext,
461 "xmlMemStrdupLoc : Unsigned overflow\n");
462 return(NULL);
463 }
464
465 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
466 if (!p) {
467 goto error;
468 }
469 p->mh_tag = MEMTAG;
470 p->mh_size = size;
471 p->mh_type = STRDUP_TYPE;
472 p->mh_file = file;
473 p->mh_line = line;
474 xmlMutexLock(&xmlMemMutex);
475 p->mh_number = ++block;
476 debugMemSize += size;
477 debugMemBlocks++;
478 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
479#ifdef MEM_LIST
480 debugmem_list_add(p);
481#endif
482 xmlMutexUnlock(&xmlMemMutex);
483
484 s = (char *) HDR_2_CLIENT(p);
485
486 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
487
488 strcpy(s,str);
489
490 TEST_POINT
491
492 if (xmlMemTraceBlockAt == s) {
493 xmlGenericError(xmlGenericErrorContext,
494 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
495 xmlMallocBreakpoint();
496 }
497
498 return(s);
499
500error:
501 return(NULL);
502}
503
504/**
505 * xmlMemoryStrdup:
506 * @str: the initial string pointer
507 *
508 * a strdup() equivalent, with logging of the allocation info.
509 *
510 * Returns a pointer to the new string or NULL if allocation error occurred.
511 */
512
513char *
514xmlMemoryStrdup(const char *str) {
515 return(xmlMemStrdupLoc(str, "none", 0));
516}
517
518/**
519 * xmlMemSize:
520 * @ptr: pointer to the memory allocation
521 *
522 * Returns the size of a memory allocation.
523 */
524
525size_t
526xmlMemSize(void *ptr) {
527 MEMHDR *p;
528
529 if (ptr == NULL)
530 return(0);
531
532 p = CLIENT_2_HDR(ptr);
533 if (p->mh_tag != MEMTAG)
534 return(0);
535
536 return(p->mh_size);
537}
538
539/**
540 * xmlMemUsed:
541 *
542 * Provides the amount of memory currently allocated
543 *
544 * Returns an int representing the amount of memory allocated.
545 */
546
547int
548xmlMemUsed(void) {
549 return(debugMemSize);
550}
551
552/**
553 * xmlMemBlocks:
554 *
555 * Provides the number of memory areas currently allocated
556 *
557 * Returns an int representing the number of blocks
558 */
559
560int
561xmlMemBlocks(void) {
562 int res;
563
564 xmlMutexLock(&xmlMemMutex);
565 res = debugMemBlocks;
566 xmlMutexUnlock(&xmlMemMutex);
567 return(res);
568}
569
570/**
571 * xmlMemDisplayLast:
572 * @fp: a FILE descriptor used as the output file, if NULL, the result is
573 * written to the file .memorylist
574 * @nbBytes: the amount of memory to dump
575 *
576 * the last nbBytes of memory allocated and not freed, useful for dumping
577 * the memory left allocated between two places at runtime.
578 */
579
580void
581xmlMemDisplayLast(FILE *fp, long nbBytes)
582{
583#ifdef MEM_LIST
584 MEMHDR *p;
585 unsigned idx;
586 int nb = 0;
587#endif
588 FILE *old_fp = fp;
589
590 if (nbBytes <= 0)
591 return;
592
593 if (fp == NULL) {
594 fp = fopen(".memorylist", "w");
595 if (fp == NULL)
596 return;
597 }
598
599#ifdef MEM_LIST
600 fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
601 nbBytes, debugMemSize, debugMaxMemSize);
602 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
603 idx = 0;
604 xmlMutexLock(&xmlMemMutex);
605 p = memlist;
606 while ((p) && (nbBytes > 0)) {
607 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
608 (unsigned long)p->mh_size);
609 switch (p->mh_type) {
610 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
611 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
612 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
613 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
614 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
615 default:
616 fprintf(fp,"Unknown memory block, may be corrupted");
617 xmlMutexUnlock(&xmlMemMutex);
618 if (old_fp == NULL)
619 fclose(fp);
620 return;
621 }
622 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
623 if (p->mh_tag != MEMTAG)
624 fprintf(fp," INVALID");
625 nb++;
626
627 fprintf(fp,"\n");
628 nbBytes -= (unsigned long)p->mh_size;
629 p = p->mh_next;
630 }
631 xmlMutexUnlock(&xmlMemMutex);
632#else
633 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
634#endif
635 if (old_fp == NULL)
636 fclose(fp);
637}
638
639/**
640 * xmlMemDisplay:
641 * @fp: a FILE descriptor used as the output file, if NULL, the result is
642 * written to the file .memorylist
643 *
644 * show in-extenso the memory blocks allocated
645 */
646
647void
648xmlMemDisplay(FILE *fp)
649{
650#ifdef MEM_LIST
651 MEMHDR *p;
652 unsigned idx;
653 int nb = 0;
654 time_t currentTime;
655 char buf[500];
656 struct tm * tstruct;
657#endif
658 FILE *old_fp = fp;
659
660 if (fp == NULL) {
661 fp = fopen(".memorylist", "w");
662 if (fp == NULL)
663 return;
664 }
665
666#ifdef MEM_LIST
667 currentTime = time(NULL);
668 tstruct = localtime(&currentTime);
669 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
670 fprintf(fp," %s\n\n", buf);
671
672
673 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
674 debugMemSize, debugMaxMemSize);
675 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
676 idx = 0;
677 xmlMutexLock(&xmlMemMutex);
678 p = memlist;
679 while (p) {
680 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
681 (unsigned long)p->mh_size);
682 switch (p->mh_type) {
683 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
684 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
685 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
686 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
687 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
688 default:
689 fprintf(fp,"Unknown memory block, may be corrupted");
690 xmlMutexUnlock(&xmlMemMutex);
691 if (old_fp == NULL)
692 fclose(fp);
693 return;
694 }
695 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
696 if (p->mh_tag != MEMTAG)
697 fprintf(fp," INVALID");
698 nb++;
699
700 fprintf(fp,"\n");
701 p = p->mh_next;
702 }
703 xmlMutexUnlock(&xmlMemMutex);
704#else
705 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
706#endif
707 if (old_fp == NULL)
708 fclose(fp);
709}
710
711#ifdef MEM_LIST
712
713static void debugmem_list_add(MEMHDR *p)
714{
715 p->mh_next = memlist;
716 p->mh_prev = NULL;
717 if (memlist) memlist->mh_prev = p;
718 memlist = p;
719}
720
721static void debugmem_list_delete(MEMHDR *p)
722{
723 if (p->mh_next)
724 p->mh_next->mh_prev = p->mh_prev;
725 if (p->mh_prev)
726 p->mh_prev->mh_next = p->mh_next;
727 else memlist = p->mh_next;
728}
729
730#endif
731
732/*
733 * debugmem_tag_error:
734 *
735 * internal error function.
736 */
737
738static void debugmem_tag_error(void *p)
739{
740 xmlGenericError(xmlGenericErrorContext,
741 "Memory tag error occurs :%p \n\t bye\n", p);
742#ifdef MEM_LIST
743 if (stderr)
744 xmlMemDisplay(stderr);
745#endif
746}
747
748#ifdef MEM_LIST
749static FILE *xmlMemoryDumpFile = NULL;
750#endif
751
752/**
753 * xmlMemShow:
754 * @fp: a FILE descriptor used as the output file
755 * @nr: number of entries to dump
756 *
757 * show a show display of the memory allocated, and dump
758 * the @nr last allocated areas which were not freed
759 */
760
761void
762xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
763{
764#ifdef MEM_LIST
765 MEMHDR *p;
766#endif
767
768 if (fp != NULL)
769 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
770 debugMemSize, debugMaxMemSize);
771#ifdef MEM_LIST
772 xmlMutexLock(&xmlMemMutex);
773 if (nr > 0) {
774 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
775 p = memlist;
776 while ((p) && nr > 0) {
777 fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
778 switch (p->mh_type) {
779 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
780 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
781 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
782 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
783 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
784 default:fprintf(fp," ??? in ");break;
785 }
786 if (p->mh_file != NULL)
787 fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
788 if (p->mh_tag != MEMTAG)
789 fprintf(fp," INVALID");
790 fprintf(fp,"\n");
791 nr--;
792 p = p->mh_next;
793 }
794 }
795 xmlMutexUnlock(&xmlMemMutex);
796#endif /* MEM_LIST */
797}
798
799/**
800 * xmlMemoryDump:
801 *
802 * Dump in-extenso the memory blocks allocated to the file .memorylist
803 */
804
805void
806xmlMemoryDump(void)
807{
808#ifdef MEM_LIST
809 FILE *dump;
810
811 if (debugMaxMemSize == 0)
812 return;
813 dump = fopen(".memdump", "w");
814 if (dump == NULL)
815 xmlMemoryDumpFile = stderr;
816 else xmlMemoryDumpFile = dump;
817
818 xmlMemDisplay(xmlMemoryDumpFile);
819
820 if (dump != NULL) fclose(dump);
821#endif /* MEM_LIST */
822}
823
824
825/****************************************************************
826 * *
827 * Initialization Routines *
828 * *
829 ****************************************************************/
830
831/**
832 * xmlInitMemory:
833 *
834 * DEPRECATED: Alias for xmlInitParser.
835 */
836int
837xmlInitMemory(void) {
838 xmlInitParser();
839 return(0);
840}
841
842/**
843 * xmlInitMemoryInternal:
844 *
845 * Initialize the memory layer.
846 *
847 * Returns 0 on success
848 */
849void
850xmlInitMemoryInternal(void) {
851
852#ifdef VBOX
853 const char *breakpoint;
854#else
855 char *breakpoint;
856#endif
857
858#ifdef DEBUG_MEMORY
859 xmlGenericError(xmlGenericErrorContext,
860 "xmlInitMemory()\n");
861#endif
862
863 xmlInitMutex(&xmlMemMutex);
864
865 breakpoint = getenv("XML_MEM_BREAKPOINT");
866 if (breakpoint != NULL) {
867 sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
868 }
869 breakpoint = getenv("XML_MEM_TRACE");
870 if (breakpoint != NULL) {
871 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
872 }
873}
874
875/**
876 * xmlCleanupMemory:
877 *
878 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
879 * to free global state but see the warnings there. xmlCleanupParser
880 * should be only called once at program exit. In most cases, you don't
881 * have call cleanup functions at all.
882 */
883void
884xmlCleanupMemory(void) {
885}
886
887/**
888 * xmlCleanupMemoryInternal:
889 *
890 * Free up all the memory allocated by the library for its own
891 * use. This should not be called by user level code.
892 */
893void
894xmlCleanupMemoryInternal(void) {
895 /*
896 * Don't clean up mutex on Windows. Global state destructors can call
897 * malloc functions after xmlCleanupParser was called. If memory
898 * debugging is enabled, xmlMemMutex can be used after cleanup.
899 *
900 * See python/tests/thread2.py
901 */
902#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
903 xmlCleanupMutex(&xmlMemMutex);
904#endif
905}
906
907/**
908 * xmlMemSetup:
909 * @freeFunc: the free() function to use
910 * @mallocFunc: the malloc() function to use
911 * @reallocFunc: the realloc() function to use
912 * @strdupFunc: the strdup() function to use
913 *
914 * Override the default memory access functions with a new set
915 * This has to be called before any other libxml routines !
916 *
917 * Should this be blocked if there was already some allocations
918 * done ?
919 *
920 * Returns 0 on success
921 */
922int
923xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
924 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
925 if (freeFunc == NULL)
926 return(-1);
927 if (mallocFunc == NULL)
928 return(-1);
929 if (reallocFunc == NULL)
930 return(-1);
931 if (strdupFunc == NULL)
932 return(-1);
933 xmlFree = freeFunc;
934 xmlMalloc = mallocFunc;
935 xmlMallocAtomic = mallocFunc;
936 xmlRealloc = reallocFunc;
937 xmlMemStrdup = strdupFunc;
938 return(0);
939}
940
941/**
942 * xmlMemGet:
943 * @freeFunc: place to save the free() function in use
944 * @mallocFunc: place to save the malloc() function in use
945 * @reallocFunc: place to save the realloc() function in use
946 * @strdupFunc: place to save the strdup() function in use
947 *
948 * Provides the memory access functions set currently in use
949 *
950 * Returns 0 on success
951 */
952int
953xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
954 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
955 if (freeFunc != NULL) *freeFunc = xmlFree;
956 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
957 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
958 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
959 return(0);
960}
961
962/**
963 * xmlGcMemSetup:
964 * @freeFunc: the free() function to use
965 * @mallocFunc: the malloc() function to use
966 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
967 * @reallocFunc: the realloc() function to use
968 * @strdupFunc: the strdup() function to use
969 *
970 * Override the default memory access functions with a new set
971 * This has to be called before any other libxml routines !
972 * The mallocAtomicFunc is specialized for atomic block
973 * allocations (i.e. of areas useful for garbage collected memory allocators
974 *
975 * Should this be blocked if there was already some allocations
976 * done ?
977 *
978 * Returns 0 on success
979 */
980int
981xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
982 xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
983 xmlStrdupFunc strdupFunc) {
984 if (freeFunc == NULL)
985 return(-1);
986 if (mallocFunc == NULL)
987 return(-1);
988 if (mallocAtomicFunc == NULL)
989 return(-1);
990 if (reallocFunc == NULL)
991 return(-1);
992 if (strdupFunc == NULL)
993 return(-1);
994 xmlFree = freeFunc;
995 xmlMalloc = mallocFunc;
996 xmlMallocAtomic = mallocAtomicFunc;
997 xmlRealloc = reallocFunc;
998 xmlMemStrdup = strdupFunc;
999 return(0);
1000}
1001
1002/**
1003 * xmlGcMemGet:
1004 * @freeFunc: place to save the free() function in use
1005 * @mallocFunc: place to save the malloc() function in use
1006 * @mallocAtomicFunc: place to save the atomic malloc() function in use
1007 * @reallocFunc: place to save the realloc() function in use
1008 * @strdupFunc: place to save the strdup() function in use
1009 *
1010 * Provides the memory access functions set currently in use
1011 * The mallocAtomicFunc is specialized for atomic block
1012 * allocations (i.e. of areas useful for garbage collected memory allocators
1013 *
1014 * Returns 0 on success
1015 */
1016int
1017xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1018 xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
1019 xmlStrdupFunc *strdupFunc) {
1020 if (freeFunc != NULL) *freeFunc = xmlFree;
1021 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1022 if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
1023 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1024 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1025 return(0);
1026}
1027
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use