wined3d: Respect the BO memory offset in wined3d_context_gl_map_bo_address().
[wine.git] / libs / xml2 / xmlmemory.c
blobc51f49ae67c2a67f4e21ed9ddc535bd54ecfc0f4
1 /*
2 * xmlmemory.c: libxml memory allocator wrapper.
4 * daniel@veillard.com
5 */
7 #define IN_LIBXML
8 #include "libxml.h"
10 #include <string.h>
12 #ifdef HAVE_SYS_TYPES_H
13 #include <sys/types.h>
14 #endif
16 #ifdef HAVE_TIME_H
17 #include <time.h>
18 #endif
20 #ifdef HAVE_STDLIB_H
21 #include <stdlib.h>
22 #else
23 #ifdef HAVE_MALLOC_H
24 #include <malloc.h>
25 #endif
26 #endif
28 #ifdef HAVE_CTYPE_H
29 #include <ctype.h>
30 #endif
32 /* #define DEBUG_MEMORY */
34 /**
35 * MEM_LIST:
37 * keep track of all allocated blocks for error reporting
38 * Always build the memory list !
40 #ifdef DEBUG_MEMORY_LOCATION
41 #ifndef MEM_LIST
42 #define MEM_LIST /* keep a list of all the allocated memory blocks */
43 #endif
44 #endif
46 #include <libxml/globals.h> /* must come before xmlmemory.h */
47 #include <libxml/xmlmemory.h>
48 #include <libxml/xmlerror.h>
49 #include <libxml/threads.h>
51 static int xmlMemInitialized = 0;
52 static unsigned long debugMemSize = 0;
53 static unsigned long debugMemBlocks = 0;
54 static unsigned long debugMaxMemSize = 0;
55 static xmlMutexPtr xmlMemMutex = NULL;
57 void xmlMallocBreakpoint(void);
59 /************************************************************************
60 * *
61 * Macros, variables and associated types *
62 * *
63 ************************************************************************/
65 #if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
66 #ifdef xmlMalloc
67 #undef xmlMalloc
68 #endif
69 #ifdef xmlRealloc
70 #undef xmlRealloc
71 #endif
72 #ifdef xmlMemStrdup
73 #undef xmlMemStrdup
74 #endif
75 #endif
78 * Each of the blocks allocated begin with a header containing information
81 #define MEMTAG 0x5aa5
83 #define MALLOC_TYPE 1
84 #define REALLOC_TYPE 2
85 #define STRDUP_TYPE 3
86 #define MALLOC_ATOMIC_TYPE 4
87 #define REALLOC_ATOMIC_TYPE 5
89 typedef struct memnod {
90 unsigned int mh_tag;
91 unsigned int mh_type;
92 unsigned long mh_number;
93 size_t mh_size;
94 #ifdef MEM_LIST
95 struct memnod *mh_next;
96 struct memnod *mh_prev;
97 #endif
98 const char *mh_file;
99 unsigned int mh_line;
100 } MEMHDR;
103 #ifdef SUN4
104 #define ALIGN_SIZE 16
105 #else
106 #define ALIGN_SIZE sizeof(double)
107 #endif
108 #define HDR_SIZE sizeof(MEMHDR)
109 #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
110 / ALIGN_SIZE ) * ALIGN_SIZE)
112 #define MAX_SIZE_T ((size_t)-1)
114 #define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
115 #define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
118 static unsigned int block=0;
119 static unsigned int xmlMemStopAtBlock = 0;
120 static void *xmlMemTraceBlockAt = NULL;
121 #ifdef MEM_LIST
122 static MEMHDR *memlist = NULL;
123 #endif
125 static void debugmem_tag_error(void *addr);
126 #ifdef MEM_LIST
127 static void debugmem_list_add(MEMHDR *);
128 static void debugmem_list_delete(MEMHDR *);
129 #endif
130 #define Mem_Tag_Err(a) debugmem_tag_error(a);
132 #ifndef TEST_POINT
133 #define TEST_POINT
134 #endif
137 * xmlMallocBreakpoint:
139 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
140 * number reaches the specified value this function is called. One need to add a breakpoint
141 * to it to get the context in which the given block is allocated.
144 void
145 xmlMallocBreakpoint(void) {
146 xmlGenericError(xmlGenericErrorContext,
147 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
151 * xmlMallocLoc:
152 * @size: an int specifying the size in byte to allocate.
153 * @file: the file name or NULL
154 * @line: the line number
156 * a malloc() equivalent, with logging of the allocation info.
158 * Returns a pointer to the allocated area or NULL in case of lack of memory.
161 void *
162 xmlMallocLoc(size_t size, const char * file, int line)
164 MEMHDR *p;
165 void *ret;
167 if (!xmlMemInitialized) xmlInitMemory();
168 #ifdef DEBUG_MEMORY
169 xmlGenericError(xmlGenericErrorContext,
170 "Malloc(%d)\n",size);
171 #endif
173 TEST_POINT
175 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
176 xmlGenericError(xmlGenericErrorContext,
177 "xmlMallocLoc : Unsigned overflow\n");
178 xmlMemoryDump();
179 return(NULL);
182 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
184 if (!p) {
185 xmlGenericError(xmlGenericErrorContext,
186 "xmlMallocLoc : Out of free space\n");
187 xmlMemoryDump();
188 return(NULL);
190 p->mh_tag = MEMTAG;
191 p->mh_size = size;
192 p->mh_type = MALLOC_TYPE;
193 p->mh_file = file;
194 p->mh_line = line;
195 xmlMutexLock(xmlMemMutex);
196 p->mh_number = ++block;
197 debugMemSize += size;
198 debugMemBlocks++;
199 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
200 #ifdef MEM_LIST
201 debugmem_list_add(p);
202 #endif
203 xmlMutexUnlock(xmlMemMutex);
205 #ifdef DEBUG_MEMORY
206 xmlGenericError(xmlGenericErrorContext,
207 "Malloc(%d) Ok\n",size);
208 #endif
210 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
212 ret = HDR_2_CLIENT(p);
214 if (xmlMemTraceBlockAt == ret) {
215 xmlGenericError(xmlGenericErrorContext,
216 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
217 (long unsigned)size);
218 xmlMallocBreakpoint();
221 TEST_POINT
223 return(ret);
227 * xmlMallocAtomicLoc:
228 * @size: an unsigned int specifying the size in byte to allocate.
229 * @file: the file name or NULL
230 * @line: the line number
232 * a malloc() equivalent, with logging of the allocation info.
234 * Returns a pointer to the allocated area or NULL in case of lack of memory.
237 void *
238 xmlMallocAtomicLoc(size_t size, const char * file, int line)
240 MEMHDR *p;
241 void *ret;
243 if (!xmlMemInitialized) xmlInitMemory();
244 #ifdef DEBUG_MEMORY
245 xmlGenericError(xmlGenericErrorContext,
246 "Malloc(%d)\n",size);
247 #endif
249 TEST_POINT
251 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
252 xmlGenericError(xmlGenericErrorContext,
253 "xmlMallocAtomicLoc : Unsigned overflow\n");
254 xmlMemoryDump();
255 return(NULL);
258 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
260 if (!p) {
261 xmlGenericError(xmlGenericErrorContext,
262 "xmlMallocAtomicLoc : Out of free space\n");
263 xmlMemoryDump();
264 return(NULL);
266 p->mh_tag = MEMTAG;
267 p->mh_size = size;
268 p->mh_type = MALLOC_ATOMIC_TYPE;
269 p->mh_file = file;
270 p->mh_line = line;
271 xmlMutexLock(xmlMemMutex);
272 p->mh_number = ++block;
273 debugMemSize += size;
274 debugMemBlocks++;
275 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
276 #ifdef MEM_LIST
277 debugmem_list_add(p);
278 #endif
279 xmlMutexUnlock(xmlMemMutex);
281 #ifdef DEBUG_MEMORY
282 xmlGenericError(xmlGenericErrorContext,
283 "Malloc(%d) Ok\n",size);
284 #endif
286 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
288 ret = HDR_2_CLIENT(p);
290 if (xmlMemTraceBlockAt == ret) {
291 xmlGenericError(xmlGenericErrorContext,
292 "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
293 (long unsigned)size);
294 xmlMallocBreakpoint();
297 TEST_POINT
299 return(ret);
302 * xmlMemMalloc:
303 * @size: an int specifying the size in byte to allocate.
305 * a malloc() equivalent, with logging of the allocation info.
307 * Returns a pointer to the allocated area or NULL in case of lack of memory.
310 void *
311 xmlMemMalloc(size_t size)
313 return(xmlMallocLoc(size, "none", 0));
317 * xmlReallocLoc:
318 * @ptr: the initial memory block pointer
319 * @size: an int specifying the size in byte to allocate.
320 * @file: the file name or NULL
321 * @line: the line number
323 * a realloc() equivalent, with logging of the allocation info.
325 * Returns a pointer to the allocated area or NULL in case of lack of memory.
328 void *
329 xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
331 MEMHDR *p, *tmp;
332 unsigned long number;
333 #ifdef DEBUG_MEMORY
334 size_t oldsize;
335 #endif
337 if (ptr == NULL)
338 return(xmlMallocLoc(size, file, line));
340 if (!xmlMemInitialized) xmlInitMemory();
341 TEST_POINT
343 p = CLIENT_2_HDR(ptr);
344 number = p->mh_number;
345 if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
346 if (p->mh_tag != MEMTAG) {
347 Mem_Tag_Err(p);
348 goto error;
350 p->mh_tag = ~MEMTAG;
351 xmlMutexLock(xmlMemMutex);
352 debugMemSize -= p->mh_size;
353 debugMemBlocks--;
354 #ifdef DEBUG_MEMORY
355 oldsize = p->mh_size;
356 #endif
357 #ifdef MEM_LIST
358 debugmem_list_delete(p);
359 #endif
360 xmlMutexUnlock(xmlMemMutex);
362 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
363 xmlGenericError(xmlGenericErrorContext,
364 "xmlReallocLoc : Unsigned overflow\n");
365 xmlMemoryDump();
366 return(NULL);
369 tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
370 if (!tmp) {
371 free(p);
372 goto error;
374 p = tmp;
375 if (xmlMemTraceBlockAt == ptr) {
376 xmlGenericError(xmlGenericErrorContext,
377 "%p : Realloced(%lu -> %lu) Ok\n",
378 xmlMemTraceBlockAt, (long unsigned)p->mh_size,
379 (long unsigned)size);
380 xmlMallocBreakpoint();
382 p->mh_tag = MEMTAG;
383 p->mh_number = number;
384 p->mh_type = REALLOC_TYPE;
385 p->mh_size = size;
386 p->mh_file = file;
387 p->mh_line = line;
388 xmlMutexLock(xmlMemMutex);
389 debugMemSize += size;
390 debugMemBlocks++;
391 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
392 #ifdef MEM_LIST
393 debugmem_list_add(p);
394 #endif
395 xmlMutexUnlock(xmlMemMutex);
397 TEST_POINT
399 #ifdef DEBUG_MEMORY
400 xmlGenericError(xmlGenericErrorContext,
401 "Realloced(%d to %d) Ok\n", oldsize, size);
402 #endif
403 return(HDR_2_CLIENT(p));
405 error:
406 return(NULL);
410 * xmlMemRealloc:
411 * @ptr: the initial memory block pointer
412 * @size: an int specifying the size in byte to allocate.
414 * a realloc() equivalent, with logging of the allocation info.
416 * Returns a pointer to the allocated area or NULL in case of lack of memory.
419 void *
420 xmlMemRealloc(void *ptr,size_t size) {
421 return(xmlReallocLoc(ptr, size, "none", 0));
425 * xmlMemFree:
426 * @ptr: the memory block pointer
428 * a free() equivalent, with error checking.
430 void
431 xmlMemFree(void *ptr)
433 MEMHDR *p;
434 char *target;
435 #ifdef DEBUG_MEMORY
436 size_t size;
437 #endif
439 if (ptr == NULL)
440 return;
442 if (ptr == (void *) -1) {
443 xmlGenericError(xmlGenericErrorContext,
444 "trying to free pointer from freed area\n");
445 goto error;
448 if (xmlMemTraceBlockAt == ptr) {
449 xmlGenericError(xmlGenericErrorContext,
450 "%p : Freed()\n", xmlMemTraceBlockAt);
451 xmlMallocBreakpoint();
454 TEST_POINT
456 target = (char *) ptr;
458 p = CLIENT_2_HDR(ptr);
459 if (p->mh_tag != MEMTAG) {
460 Mem_Tag_Err(p);
461 goto error;
463 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
464 p->mh_tag = ~MEMTAG;
465 memset(target, -1, p->mh_size);
466 xmlMutexLock(xmlMemMutex);
467 debugMemSize -= p->mh_size;
468 debugMemBlocks--;
469 #ifdef DEBUG_MEMORY
470 size = p->mh_size;
471 #endif
472 #ifdef MEM_LIST
473 debugmem_list_delete(p);
474 #endif
475 xmlMutexUnlock(xmlMemMutex);
477 free(p);
479 TEST_POINT
481 #ifdef DEBUG_MEMORY
482 xmlGenericError(xmlGenericErrorContext,
483 "Freed(%d) Ok\n", size);
484 #endif
486 return;
488 error:
489 xmlGenericError(xmlGenericErrorContext,
490 "xmlMemFree(%p) error\n", ptr);
491 xmlMallocBreakpoint();
492 return;
496 * xmlMemStrdupLoc:
497 * @str: the initial string pointer
498 * @file: the file name or NULL
499 * @line: the line number
501 * a strdup() equivalent, with logging of the allocation info.
503 * Returns a pointer to the new string or NULL if allocation error occurred.
506 char *
507 xmlMemStrdupLoc(const char *str, const char *file, int line)
509 char *s;
510 size_t size = strlen(str) + 1;
511 MEMHDR *p;
513 if (!xmlMemInitialized) xmlInitMemory();
514 TEST_POINT
516 if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
517 xmlGenericError(xmlGenericErrorContext,
518 "xmlMemStrdupLoc : Unsigned overflow\n");
519 xmlMemoryDump();
520 return(NULL);
523 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
524 if (!p) {
525 goto error;
527 p->mh_tag = MEMTAG;
528 p->mh_size = size;
529 p->mh_type = STRDUP_TYPE;
530 p->mh_file = file;
531 p->mh_line = line;
532 xmlMutexLock(xmlMemMutex);
533 p->mh_number = ++block;
534 debugMemSize += size;
535 debugMemBlocks++;
536 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
537 #ifdef MEM_LIST
538 debugmem_list_add(p);
539 #endif
540 xmlMutexUnlock(xmlMemMutex);
542 s = (char *) HDR_2_CLIENT(p);
544 if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
546 strcpy(s,str);
548 TEST_POINT
550 if (xmlMemTraceBlockAt == s) {
551 xmlGenericError(xmlGenericErrorContext,
552 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
553 xmlMallocBreakpoint();
556 return(s);
558 error:
559 return(NULL);
563 * xmlMemoryStrdup:
564 * @str: the initial string pointer
566 * a strdup() equivalent, with logging of the allocation info.
568 * Returns a pointer to the new string or NULL if allocation error occurred.
571 char *
572 xmlMemoryStrdup(const char *str) {
573 return(xmlMemStrdupLoc(str, "none", 0));
577 * xmlMemUsed:
579 * Provides the amount of memory currently allocated
581 * Returns an int representing the amount of memory allocated.
585 xmlMemUsed(void) {
586 int res;
588 xmlMutexLock(xmlMemMutex);
589 res = debugMemSize;
590 xmlMutexUnlock(xmlMemMutex);
591 return(res);
595 * xmlMemBlocks:
597 * Provides the number of memory areas currently allocated
599 * Returns an int representing the number of blocks
603 xmlMemBlocks(void) {
604 int res;
606 xmlMutexLock(xmlMemMutex);
607 res = debugMemBlocks;
608 xmlMutexUnlock(xmlMemMutex);
609 return(res);
612 #ifdef MEM_LIST
614 * xmlMemContentShow:
615 * @fp: a FILE descriptor used as the output file
616 * @p: a memory block header
618 * tries to show some content from the memory block
621 static void
622 xmlMemContentShow(FILE *fp, MEMHDR *p)
624 int i,j,k,len;
625 const char *buf;
627 if (p == NULL) {
628 fprintf(fp, " NULL");
629 return;
631 len = p->mh_size;
632 buf = (const char *) HDR_2_CLIENT(p);
634 for (i = 0;i < len;i++) {
635 if (buf[i] == 0) break;
636 if (!isprint((unsigned char) buf[i])) break;
638 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
639 if (len >= 4) {
640 MEMHDR *q;
641 void *cur;
643 for (j = 0;(j < len -3) && (j < 40);j += 4) {
644 cur = *((void **) &buf[j]);
645 q = CLIENT_2_HDR(cur);
646 p = memlist;
647 k = 0;
648 while (p != NULL) {
649 if (p == q) break;
650 p = p->mh_next;
651 if (k++ > 100) break;
653 if ((p != NULL) && (p == q)) {
654 fprintf(fp, " pointer to #%lu at index %d",
655 p->mh_number, j);
656 return;
660 } else if ((i == 0) && (buf[i] == 0)) {
661 fprintf(fp," null");
662 } else {
663 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
664 else {
665 fprintf(fp," [");
666 for (j = 0;j < i;j++)
667 fprintf(fp,"%c", buf[j]);
668 fprintf(fp,"]");
672 #endif
675 * xmlMemDisplayLast:
676 * @fp: a FILE descriptor used as the output file, if NULL, the result is
677 * written to the file .memorylist
678 * @nbBytes: the amount of memory to dump
680 * the last nbBytes of memory allocated and not freed, useful for dumping
681 * the memory left allocated between two places at runtime.
684 void
685 xmlMemDisplayLast(FILE *fp, long nbBytes)
687 #ifdef MEM_LIST
688 MEMHDR *p;
689 unsigned idx;
690 int nb = 0;
691 #endif
692 FILE *old_fp = fp;
694 if (nbBytes <= 0)
695 return;
697 if (fp == NULL) {
698 fp = fopen(".memorylist", "w");
699 if (fp == NULL)
700 return;
703 #ifdef MEM_LIST
704 fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
705 nbBytes, debugMemSize, debugMaxMemSize);
706 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
707 idx = 0;
708 xmlMutexLock(xmlMemMutex);
709 p = memlist;
710 while ((p) && (nbBytes > 0)) {
711 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
712 (unsigned long)p->mh_size);
713 switch (p->mh_type) {
714 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
715 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
716 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
717 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
718 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
719 default:
720 fprintf(fp,"Unknown memory block, may be corrupted");
721 xmlMutexUnlock(xmlMemMutex);
722 if (old_fp == NULL)
723 fclose(fp);
724 return;
726 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
727 if (p->mh_tag != MEMTAG)
728 fprintf(fp," INVALID");
729 nb++;
730 if (nb < 100)
731 xmlMemContentShow(fp, p);
732 else
733 fprintf(fp," skip");
735 fprintf(fp,"\n");
736 nbBytes -= (unsigned long)p->mh_size;
737 p = p->mh_next;
739 xmlMutexUnlock(xmlMemMutex);
740 #else
741 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
742 #endif
743 if (old_fp == NULL)
744 fclose(fp);
748 * xmlMemDisplay:
749 * @fp: a FILE descriptor used as the output file, if NULL, the result is
750 * written to the file .memorylist
752 * show in-extenso the memory blocks allocated
755 void
756 xmlMemDisplay(FILE *fp)
758 #ifdef MEM_LIST
759 MEMHDR *p;
760 unsigned idx;
761 int nb = 0;
762 #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
763 time_t currentTime;
764 char buf[500];
765 struct tm * tstruct;
766 #endif
767 #endif
768 FILE *old_fp = fp;
770 if (fp == NULL) {
771 fp = fopen(".memorylist", "w");
772 if (fp == NULL)
773 return;
776 #ifdef MEM_LIST
777 #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
778 currentTime = time(NULL);
779 tstruct = localtime(&currentTime);
780 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
781 fprintf(fp," %s\n\n", buf);
782 #endif
785 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
786 debugMemSize, debugMaxMemSize);
787 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
788 idx = 0;
789 xmlMutexLock(xmlMemMutex);
790 p = memlist;
791 while (p) {
792 fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
793 (unsigned long)p->mh_size);
794 switch (p->mh_type) {
795 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
796 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
797 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
798 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
799 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
800 default:
801 fprintf(fp,"Unknown memory block, may be corrupted");
802 xmlMutexUnlock(xmlMemMutex);
803 if (old_fp == NULL)
804 fclose(fp);
805 return;
807 if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
808 if (p->mh_tag != MEMTAG)
809 fprintf(fp," INVALID");
810 nb++;
811 if (nb < 100)
812 xmlMemContentShow(fp, p);
813 else
814 fprintf(fp," skip");
816 fprintf(fp,"\n");
817 p = p->mh_next;
819 xmlMutexUnlock(xmlMemMutex);
820 #else
821 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
822 #endif
823 if (old_fp == NULL)
824 fclose(fp);
827 #ifdef MEM_LIST
829 static void debugmem_list_add(MEMHDR *p)
831 p->mh_next = memlist;
832 p->mh_prev = NULL;
833 if (memlist) memlist->mh_prev = p;
834 memlist = p;
835 #ifdef MEM_LIST_DEBUG
836 if (stderr)
837 Mem_Display(stderr);
838 #endif
841 static void debugmem_list_delete(MEMHDR *p)
843 if (p->mh_next)
844 p->mh_next->mh_prev = p->mh_prev;
845 if (p->mh_prev)
846 p->mh_prev->mh_next = p->mh_next;
847 else memlist = p->mh_next;
848 #ifdef MEM_LIST_DEBUG
849 if (stderr)
850 Mem_Display(stderr);
851 #endif
854 #endif
857 * debugmem_tag_error:
859 * internal error function.
862 static void debugmem_tag_error(void *p)
864 xmlGenericError(xmlGenericErrorContext,
865 "Memory tag error occurs :%p \n\t bye\n", p);
866 #ifdef MEM_LIST
867 if (stderr)
868 xmlMemDisplay(stderr);
869 #endif
872 #ifdef MEM_LIST
873 static FILE *xmlMemoryDumpFile = NULL;
874 #endif
877 * xmlMemShow:
878 * @fp: a FILE descriptor used as the output file
879 * @nr: number of entries to dump
881 * show a show display of the memory allocated, and dump
882 * the @nr last allocated areas which were not freed
885 void
886 xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
888 #ifdef MEM_LIST
889 MEMHDR *p;
890 #endif
892 if (fp != NULL)
893 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
894 debugMemSize, debugMaxMemSize);
895 #ifdef MEM_LIST
896 xmlMutexLock(xmlMemMutex);
897 if (nr > 0) {
898 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
899 p = memlist;
900 while ((p) && nr > 0) {
901 fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
902 switch (p->mh_type) {
903 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
904 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
905 case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
906 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
907 case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
908 default:fprintf(fp," ??? in ");break;
910 if (p->mh_file != NULL)
911 fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
912 if (p->mh_tag != MEMTAG)
913 fprintf(fp," INVALID");
914 xmlMemContentShow(fp, p);
915 fprintf(fp,"\n");
916 nr--;
917 p = p->mh_next;
920 xmlMutexUnlock(xmlMemMutex);
921 #endif /* MEM_LIST */
925 * xmlMemoryDump:
927 * Dump in-extenso the memory blocks allocated to the file .memorylist
930 void
931 xmlMemoryDump(void)
933 #ifdef MEM_LIST
934 FILE *dump;
936 if (debugMaxMemSize == 0)
937 return;
938 dump = fopen(".memdump", "w");
939 if (dump == NULL)
940 xmlMemoryDumpFile = stderr;
941 else xmlMemoryDumpFile = dump;
943 xmlMemDisplay(xmlMemoryDumpFile);
945 if (dump != NULL) fclose(dump);
946 #endif /* MEM_LIST */
950 /****************************************************************
952 * Initialization Routines *
954 ****************************************************************/
957 * xmlInitMemory:
959 * Initialize the memory layer.
961 * Returns 0 on success
964 xmlInitMemory(void)
966 #ifdef HAVE_STDLIB_H
967 char *breakpoint;
968 #endif
969 #ifdef DEBUG_MEMORY
970 xmlGenericError(xmlGenericErrorContext,
971 "xmlInitMemory()\n");
972 #endif
974 This is really not good code (see Bug 130419). Suggestions for
975 improvement will be welcome!
977 if (xmlMemInitialized) return(-1);
978 xmlMemInitialized = 1;
979 xmlMemMutex = xmlNewMutex();
981 #ifdef HAVE_STDLIB_H
982 breakpoint = getenv("XML_MEM_BREAKPOINT");
983 if (breakpoint != NULL) {
984 sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
986 #endif
987 #ifdef HAVE_STDLIB_H
988 breakpoint = getenv("XML_MEM_TRACE");
989 if (breakpoint != NULL) {
990 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
992 #endif
994 #ifdef DEBUG_MEMORY
995 xmlGenericError(xmlGenericErrorContext,
996 "xmlInitMemory() Ok\n");
997 #endif
998 return(0);
1002 * xmlCleanupMemory:
1004 * Free up all the memory allocated by the library for its own
1005 * use. This should not be called by user level code.
1007 void
1008 xmlCleanupMemory(void) {
1009 #ifdef DEBUG_MEMORY
1010 xmlGenericError(xmlGenericErrorContext,
1011 "xmlCleanupMemory()\n");
1012 #endif
1013 if (xmlMemInitialized == 0)
1014 return;
1016 xmlFreeMutex(xmlMemMutex);
1017 xmlMemMutex = NULL;
1018 xmlMemInitialized = 0;
1019 #ifdef DEBUG_MEMORY
1020 xmlGenericError(xmlGenericErrorContext,
1021 "xmlCleanupMemory() Ok\n");
1022 #endif
1026 * xmlMemSetup:
1027 * @freeFunc: the free() function to use
1028 * @mallocFunc: the malloc() function to use
1029 * @reallocFunc: the realloc() function to use
1030 * @strdupFunc: the strdup() function to use
1032 * Override the default memory access functions with a new set
1033 * This has to be called before any other libxml routines !
1035 * Should this be blocked if there was already some allocations
1036 * done ?
1038 * Returns 0 on success
1041 xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
1042 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
1043 #ifdef DEBUG_MEMORY
1044 xmlGenericError(xmlGenericErrorContext,
1045 "xmlMemSetup()\n");
1046 #endif
1047 if (freeFunc == NULL)
1048 return(-1);
1049 if (mallocFunc == NULL)
1050 return(-1);
1051 if (reallocFunc == NULL)
1052 return(-1);
1053 if (strdupFunc == NULL)
1054 return(-1);
1055 xmlFree = freeFunc;
1056 xmlMalloc = mallocFunc;
1057 xmlMallocAtomic = mallocFunc;
1058 xmlRealloc = reallocFunc;
1059 xmlMemStrdup = strdupFunc;
1060 #ifdef DEBUG_MEMORY
1061 xmlGenericError(xmlGenericErrorContext,
1062 "xmlMemSetup() Ok\n");
1063 #endif
1064 return(0);
1068 * xmlMemGet:
1069 * @freeFunc: place to save the free() function in use
1070 * @mallocFunc: place to save the malloc() function in use
1071 * @reallocFunc: place to save the realloc() function in use
1072 * @strdupFunc: place to save the strdup() function in use
1074 * Provides the memory access functions set currently in use
1076 * Returns 0 on success
1079 xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1080 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
1081 if (freeFunc != NULL) *freeFunc = xmlFree;
1082 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1083 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1084 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1085 return(0);
1089 * xmlGcMemSetup:
1090 * @freeFunc: the free() function to use
1091 * @mallocFunc: the malloc() function to use
1092 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
1093 * @reallocFunc: the realloc() function to use
1094 * @strdupFunc: the strdup() function to use
1096 * Override the default memory access functions with a new set
1097 * This has to be called before any other libxml routines !
1098 * The mallocAtomicFunc is specialized for atomic block
1099 * allocations (i.e. of areas useful for garbage collected memory allocators
1101 * Should this be blocked if there was already some allocations
1102 * done ?
1104 * Returns 0 on success
1107 xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
1108 xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
1109 xmlStrdupFunc strdupFunc) {
1110 #ifdef DEBUG_MEMORY
1111 xmlGenericError(xmlGenericErrorContext,
1112 "xmlGcMemSetup()\n");
1113 #endif
1114 if (freeFunc == NULL)
1115 return(-1);
1116 if (mallocFunc == NULL)
1117 return(-1);
1118 if (mallocAtomicFunc == NULL)
1119 return(-1);
1120 if (reallocFunc == NULL)
1121 return(-1);
1122 if (strdupFunc == NULL)
1123 return(-1);
1124 xmlFree = freeFunc;
1125 xmlMalloc = mallocFunc;
1126 xmlMallocAtomic = mallocAtomicFunc;
1127 xmlRealloc = reallocFunc;
1128 xmlMemStrdup = strdupFunc;
1129 #ifdef DEBUG_MEMORY
1130 xmlGenericError(xmlGenericErrorContext,
1131 "xmlGcMemSetup() Ok\n");
1132 #endif
1133 return(0);
1137 * xmlGcMemGet:
1138 * @freeFunc: place to save the free() function in use
1139 * @mallocFunc: place to save the malloc() function in use
1140 * @mallocAtomicFunc: place to save the atomic malloc() function in use
1141 * @reallocFunc: place to save the realloc() function in use
1142 * @strdupFunc: place to save the strdup() function in use
1144 * Provides the memory access functions set currently in use
1145 * The mallocAtomicFunc is specialized for atomic block
1146 * allocations (i.e. of areas useful for garbage collected memory allocators
1148 * Returns 0 on success
1151 xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
1152 xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
1153 xmlStrdupFunc *strdupFunc) {
1154 if (freeFunc != NULL) *freeFunc = xmlFree;
1155 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
1156 if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
1157 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
1158 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1159 return(0);
1162 #define bottom_xmlmemory
1163 #include "elfgcchack.h"