VirtualBox

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

最後變更 在這個檔案從104106是 104106,由 vboxsync 提交於 10 月 前

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette