| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- /*
- * xmlmemory.c: libxml memory allocator wrapper.
- *
- * daniel@veillard.com
- */
- #define IN_LIBXML
- #include "libxml.h"
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <time.h>
- /**
- * MEM_LIST:
- *
- * keep track of all allocated blocks for error reporting
- * Always build the memory list !
- */
- #ifdef DEBUG_MEMORY_LOCATION
- #ifndef MEM_LIST
- #define MEM_LIST /* keep a list of all the allocated memory blocks */
- #endif
- #endif
- #include <libxml/xmlmemory.h>
- #include <libxml/xmlerror.h>
- #include <libxml/parser.h>
- #include <libxml/threads.h>
- #include "private/memory.h"
- #include "private/threads.h"
- static unsigned long debugMemSize = 0;
- static unsigned long debugMemBlocks = 0;
- static unsigned long debugMaxMemSize = 0;
- static xmlMutex xmlMemMutex;
- void xmlMallocBreakpoint(void);
- /************************************************************************
- * *
- * Macros, variables and associated types *
- * *
- ************************************************************************/
- #if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
- #ifdef xmlMalloc
- #undef xmlMalloc
- #endif
- #ifdef xmlRealloc
- #undef xmlRealloc
- #endif
- #ifdef xmlMemStrdup
- #undef xmlMemStrdup
- #endif
- #endif
- /*
- * Each of the blocks allocated begin with a header containing information
- */
- #define MEMTAG 0x5aa5U
- #define MALLOC_TYPE 1
- #define REALLOC_TYPE 2
- #define STRDUP_TYPE 3
- #define MALLOC_ATOMIC_TYPE 4
- #define REALLOC_ATOMIC_TYPE 5
- typedef struct memnod {
- unsigned int mh_tag;
- unsigned int mh_type;
- unsigned long mh_number;
- size_t mh_size;
- #ifdef MEM_LIST
- struct memnod *mh_next;
- struct memnod *mh_prev;
- #endif
- const char *mh_file;
- unsigned int mh_line;
- } MEMHDR;
- #ifdef SUN4
- #define ALIGN_SIZE 16
- #else
- #define ALIGN_SIZE sizeof(double)
- #endif
- #define HDR_SIZE sizeof(MEMHDR)
- #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
- / ALIGN_SIZE ) * ALIGN_SIZE)
- #define MAX_SIZE_T ((size_t)-1)
- #define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
- #define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
- static unsigned int block=0;
- static unsigned int xmlMemStopAtBlock = 0;
- static void *xmlMemTraceBlockAt = NULL;
- #ifdef MEM_LIST
- static MEMHDR *memlist = NULL;
- #endif
- static void debugmem_tag_error(void *addr);
- #ifdef MEM_LIST
- static void debugmem_list_add(MEMHDR *);
- static void debugmem_list_delete(MEMHDR *);
- #endif
- #define Mem_Tag_Err(a) debugmem_tag_error(a);
- #ifndef TEST_POINT
- #define TEST_POINT
- #endif
- /**
- * xmlMallocBreakpoint:
- *
- * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
- * number reaches the specified value this function is called. One need to add a breakpoint
- * to it to get the context in which the given block is allocated.
- */
- void
- xmlMallocBreakpoint(void) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
- }
- /**
- * xmlMallocLoc:
- * @size: an int specifying the size in byte to allocate.
- * @file: the file name or NULL
- * @line: the line number
- *
- * a malloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
- void *
- xmlMallocLoc(size_t size, const char * file, int line)
- {
- MEMHDR *p;
- void *ret;
- xmlInitParser();
- TEST_POINT
- if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMallocLoc : Unsigned overflow\n");
- return(NULL);
- }
- p = (MEMHDR *) malloc(RESERVE_SIZE+size);
- if (!p) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMallocLoc : Out of free space\n");
- return(NULL);
- }
- p->mh_tag = MEMTAG;
- p->mh_size = size;
- p->mh_type = MALLOC_TYPE;
- p->mh_file = file;
- p->mh_line = line;
- xmlMutexLock(&xmlMemMutex);
- p->mh_number = ++block;
- debugMemSize += size;
- debugMemBlocks++;
- if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
- #ifdef MEM_LIST
- debugmem_list_add(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
- ret = HDR_2_CLIENT(p);
- if (xmlMemTraceBlockAt == ret) {
- xmlGenericError(xmlGenericErrorContext,
- "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
- (long unsigned)size);
- xmlMallocBreakpoint();
- }
- TEST_POINT
- return(ret);
- }
- /**
- * xmlMallocAtomicLoc:
- * @size: an unsigned int specifying the size in byte to allocate.
- * @file: the file name or NULL
- * @line: the line number
- *
- * a malloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
- void *
- xmlMallocAtomicLoc(size_t size, const char * file, int line)
- {
- MEMHDR *p;
- void *ret;
- xmlInitParser();
- TEST_POINT
- if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMallocAtomicLoc : Unsigned overflow\n");
- return(NULL);
- }
- p = (MEMHDR *) malloc(RESERVE_SIZE+size);
- if (!p) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMallocAtomicLoc : Out of free space\n");
- return(NULL);
- }
- p->mh_tag = MEMTAG;
- p->mh_size = size;
- p->mh_type = MALLOC_ATOMIC_TYPE;
- p->mh_file = file;
- p->mh_line = line;
- xmlMutexLock(&xmlMemMutex);
- p->mh_number = ++block;
- debugMemSize += size;
- debugMemBlocks++;
- if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
- #ifdef MEM_LIST
- debugmem_list_add(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
- ret = HDR_2_CLIENT(p);
- if (xmlMemTraceBlockAt == ret) {
- xmlGenericError(xmlGenericErrorContext,
- "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
- (long unsigned)size);
- xmlMallocBreakpoint();
- }
- TEST_POINT
- return(ret);
- }
- /**
- * xmlMemMalloc:
- * @size: an int specifying the size in byte to allocate.
- *
- * a malloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
- void *
- xmlMemMalloc(size_t size)
- {
- return(xmlMallocLoc(size, "none", 0));
- }
- /**
- * xmlReallocLoc:
- * @ptr: the initial memory block pointer
- * @size: an int specifying the size in byte to allocate.
- * @file: the file name or NULL
- * @line: the line number
- *
- * a realloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
- void *
- xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
- {
- MEMHDR *p, *tmp;
- unsigned long number;
- if (ptr == NULL)
- return(xmlMallocLoc(size, file, line));
- xmlInitParser();
- TEST_POINT
- p = CLIENT_2_HDR(ptr);
- number = p->mh_number;
- if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
- if (p->mh_tag != MEMTAG) {
- Mem_Tag_Err(p);
- goto error;
- }
- p->mh_tag = ~MEMTAG;
- xmlMutexLock(&xmlMemMutex);
- debugMemSize -= p->mh_size;
- debugMemBlocks--;
- #ifdef MEM_LIST
- debugmem_list_delete(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlReallocLoc : Unsigned overflow\n");
- return(NULL);
- }
- tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
- if (!tmp) {
- free(p);
- goto error;
- }
- p = tmp;
- if (xmlMemTraceBlockAt == ptr) {
- xmlGenericError(xmlGenericErrorContext,
- "%p : Realloced(%lu -> %lu) Ok\n",
- xmlMemTraceBlockAt, (long unsigned)p->mh_size,
- (long unsigned)size);
- xmlMallocBreakpoint();
- }
- p->mh_tag = MEMTAG;
- p->mh_number = number;
- p->mh_type = REALLOC_TYPE;
- p->mh_size = size;
- p->mh_file = file;
- p->mh_line = line;
- xmlMutexLock(&xmlMemMutex);
- debugMemSize += size;
- debugMemBlocks++;
- if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
- #ifdef MEM_LIST
- debugmem_list_add(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- TEST_POINT
- return(HDR_2_CLIENT(p));
- error:
- return(NULL);
- }
- /**
- * xmlMemRealloc:
- * @ptr: the initial memory block pointer
- * @size: an int specifying the size in byte to allocate.
- *
- * a realloc() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the allocated area or NULL in case of lack of memory.
- */
- void *
- xmlMemRealloc(void *ptr,size_t size) {
- return(xmlReallocLoc(ptr, size, "none", 0));
- }
- /**
- * xmlMemFree:
- * @ptr: the memory block pointer
- *
- * a free() equivalent, with error checking.
- */
- void
- xmlMemFree(void *ptr)
- {
- MEMHDR *p;
- char *target;
- if (ptr == NULL)
- return;
- if (ptr == (void *) -1) {
- xmlGenericError(xmlGenericErrorContext,
- "trying to free pointer from freed area\n");
- goto error;
- }
- if (xmlMemTraceBlockAt == ptr) {
- xmlGenericError(xmlGenericErrorContext,
- "%p : Freed()\n", xmlMemTraceBlockAt);
- xmlMallocBreakpoint();
- }
- TEST_POINT
- target = (char *) ptr;
- p = CLIENT_2_HDR(ptr);
- if (p->mh_tag != MEMTAG) {
- Mem_Tag_Err(p);
- goto error;
- }
- if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
- p->mh_tag = ~MEMTAG;
- memset(target, -1, p->mh_size);
- xmlMutexLock(&xmlMemMutex);
- debugMemSize -= p->mh_size;
- debugMemBlocks--;
- #ifdef MEM_LIST
- debugmem_list_delete(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- free(p);
- TEST_POINT
- return;
- error:
- xmlGenericError(xmlGenericErrorContext,
- "xmlMemFree(%p) error\n", ptr);
- xmlMallocBreakpoint();
- return;
- }
- /**
- * xmlMemStrdupLoc:
- * @str: the initial string pointer
- * @file: the file name or NULL
- * @line: the line number
- *
- * a strdup() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the new string or NULL if allocation error occurred.
- */
- char *
- xmlMemStrdupLoc(const char *str, const char *file, int line)
- {
- char *s;
- size_t size = strlen(str) + 1;
- MEMHDR *p;
- xmlInitParser();
- TEST_POINT
- if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlMemStrdupLoc : Unsigned overflow\n");
- return(NULL);
- }
- p = (MEMHDR *) malloc(RESERVE_SIZE+size);
- if (!p) {
- goto error;
- }
- p->mh_tag = MEMTAG;
- p->mh_size = size;
- p->mh_type = STRDUP_TYPE;
- p->mh_file = file;
- p->mh_line = line;
- xmlMutexLock(&xmlMemMutex);
- p->mh_number = ++block;
- debugMemSize += size;
- debugMemBlocks++;
- if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
- #ifdef MEM_LIST
- debugmem_list_add(p);
- #endif
- xmlMutexUnlock(&xmlMemMutex);
- s = (char *) HDR_2_CLIENT(p);
- if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
- strcpy(s,str);
- TEST_POINT
- if (xmlMemTraceBlockAt == s) {
- xmlGenericError(xmlGenericErrorContext,
- "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
- xmlMallocBreakpoint();
- }
- return(s);
- error:
- return(NULL);
- }
- /**
- * xmlMemoryStrdup:
- * @str: the initial string pointer
- *
- * a strdup() equivalent, with logging of the allocation info.
- *
- * Returns a pointer to the new string or NULL if allocation error occurred.
- */
- char *
- xmlMemoryStrdup(const char *str) {
- return(xmlMemStrdupLoc(str, "none", 0));
- }
- /**
- * xmlMemSize:
- * @ptr: pointer to the memory allocation
- *
- * Returns the size of a memory allocation.
- */
- size_t
- xmlMemSize(void *ptr) {
- MEMHDR *p;
- if (ptr == NULL)
- return(0);
- p = CLIENT_2_HDR(ptr);
- if (p->mh_tag != MEMTAG)
- return(0);
- return(p->mh_size);
- }
- /**
- * xmlMemUsed:
- *
- * Provides the amount of memory currently allocated
- *
- * Returns an int representing the amount of memory allocated.
- */
- int
- xmlMemUsed(void) {
- return(debugMemSize);
- }
- /**
- * xmlMemBlocks:
- *
- * Provides the number of memory areas currently allocated
- *
- * Returns an int representing the number of blocks
- */
- int
- xmlMemBlocks(void) {
- int res;
- xmlMutexLock(&xmlMemMutex);
- res = debugMemBlocks;
- xmlMutexUnlock(&xmlMemMutex);
- return(res);
- }
- /**
- * xmlMemDisplayLast:
- * @fp: a FILE descriptor used as the output file, if NULL, the result is
- * written to the file .memorylist
- * @nbBytes: the amount of memory to dump
- *
- * the last nbBytes of memory allocated and not freed, useful for dumping
- * the memory left allocated between two places at runtime.
- */
- void
- xmlMemDisplayLast(FILE *fp, long nbBytes)
- {
- #ifdef MEM_LIST
- MEMHDR *p;
- unsigned idx;
- int nb = 0;
- #endif
- FILE *old_fp = fp;
- if (nbBytes <= 0)
- return;
- if (fp == NULL) {
- fp = fopen(".memorylist", "w");
- if (fp == NULL)
- return;
- }
- #ifdef MEM_LIST
- fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
- nbBytes, debugMemSize, debugMaxMemSize);
- fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
- idx = 0;
- xmlMutexLock(&xmlMemMutex);
- p = memlist;
- while ((p) && (nbBytes > 0)) {
- fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
- (unsigned long)p->mh_size);
- switch (p->mh_type) {
- case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
- case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
- case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
- case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
- case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
- default:
- fprintf(fp,"Unknown memory block, may be corrupted");
- xmlMutexUnlock(&xmlMemMutex);
- if (old_fp == NULL)
- fclose(fp);
- return;
- }
- if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
- if (p->mh_tag != MEMTAG)
- fprintf(fp," INVALID");
- nb++;
- fprintf(fp,"\n");
- nbBytes -= (unsigned long)p->mh_size;
- p = p->mh_next;
- }
- xmlMutexUnlock(&xmlMemMutex);
- #else
- fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
- #endif
- if (old_fp == NULL)
- fclose(fp);
- }
- /**
- * xmlMemDisplay:
- * @fp: a FILE descriptor used as the output file, if NULL, the result is
- * written to the file .memorylist
- *
- * show in-extenso the memory blocks allocated
- */
- void
- xmlMemDisplay(FILE *fp)
- {
- #ifdef MEM_LIST
- MEMHDR *p;
- unsigned idx;
- int nb = 0;
- time_t currentTime;
- char buf[500];
- struct tm * tstruct;
- #endif
- FILE *old_fp = fp;
- if (fp == NULL) {
- fp = fopen(".memorylist", "w");
- if (fp == NULL)
- return;
- }
- #ifdef MEM_LIST
- currentTime = time(NULL);
- tstruct = localtime(¤tTime);
- strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
- fprintf(fp," %s\n\n", buf);
- fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
- debugMemSize, debugMaxMemSize);
- fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
- idx = 0;
- xmlMutexLock(&xmlMemMutex);
- p = memlist;
- while (p) {
- fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number,
- (unsigned long)p->mh_size);
- switch (p->mh_type) {
- case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
- case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
- case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
- case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
- case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
- default:
- fprintf(fp,"Unknown memory block, may be corrupted");
- xmlMutexUnlock(&xmlMemMutex);
- if (old_fp == NULL)
- fclose(fp);
- return;
- }
- if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
- if (p->mh_tag != MEMTAG)
- fprintf(fp," INVALID");
- nb++;
- fprintf(fp,"\n");
- p = p->mh_next;
- }
- xmlMutexUnlock(&xmlMemMutex);
- #else
- fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
- #endif
- if (old_fp == NULL)
- fclose(fp);
- }
- #ifdef MEM_LIST
- static void debugmem_list_add(MEMHDR *p)
- {
- p->mh_next = memlist;
- p->mh_prev = NULL;
- if (memlist) memlist->mh_prev = p;
- memlist = p;
- }
- static void debugmem_list_delete(MEMHDR *p)
- {
- if (p->mh_next)
- p->mh_next->mh_prev = p->mh_prev;
- if (p->mh_prev)
- p->mh_prev->mh_next = p->mh_next;
- else memlist = p->mh_next;
- }
- #endif
- /*
- * debugmem_tag_error:
- *
- * internal error function.
- */
- static void debugmem_tag_error(void *p)
- {
- xmlGenericError(xmlGenericErrorContext,
- "Memory tag error occurs :%p \n\t bye\n", p);
- #ifdef MEM_LIST
- if (stderr)
- xmlMemDisplay(stderr);
- #endif
- }
- #ifdef MEM_LIST
- static FILE *xmlMemoryDumpFile = NULL;
- #endif
- /**
- * xmlMemShow:
- * @fp: a FILE descriptor used as the output file
- * @nr: number of entries to dump
- *
- * show a show display of the memory allocated, and dump
- * the @nr last allocated areas which were not freed
- */
- void
- xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
- {
- #ifdef MEM_LIST
- MEMHDR *p;
- #endif
- if (fp != NULL)
- fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
- debugMemSize, debugMaxMemSize);
- #ifdef MEM_LIST
- xmlMutexLock(&xmlMemMutex);
- if (nr > 0) {
- fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
- p = memlist;
- while ((p) && nr > 0) {
- fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
- switch (p->mh_type) {
- case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
- case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
- case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break;
- case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
- case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
- default:fprintf(fp," ??? in ");break;
- }
- if (p->mh_file != NULL)
- fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
- if (p->mh_tag != MEMTAG)
- fprintf(fp," INVALID");
- fprintf(fp,"\n");
- nr--;
- p = p->mh_next;
- }
- }
- xmlMutexUnlock(&xmlMemMutex);
- #endif /* MEM_LIST */
- }
- /**
- * xmlMemoryDump:
- *
- * Dump in-extenso the memory blocks allocated to the file .memorylist
- */
- void
- xmlMemoryDump(void)
- {
- #ifdef MEM_LIST
- FILE *dump;
- if (debugMaxMemSize == 0)
- return;
- dump = fopen(".memdump", "w");
- if (dump == NULL)
- xmlMemoryDumpFile = stderr;
- else xmlMemoryDumpFile = dump;
- xmlMemDisplay(xmlMemoryDumpFile);
- if (dump != NULL) fclose(dump);
- #endif /* MEM_LIST */
- }
- /****************************************************************
- * *
- * Initialization Routines *
- * *
- ****************************************************************/
- /**
- * xmlInitMemory:
- *
- * DEPRECATED: Alias for xmlInitParser.
- */
- int
- xmlInitMemory(void) {
- xmlInitParser();
- return(0);
- }
- /**
- * xmlInitMemoryInternal:
- *
- * Initialize the memory layer.
- *
- * Returns 0 on success
- */
- void
- xmlInitMemoryInternal(void) {
- char *breakpoint;
- xmlInitMutex(&xmlMemMutex);
- breakpoint = getenv("XML_MEM_BREAKPOINT");
- if (breakpoint != NULL) {
- sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
- }
- breakpoint = getenv("XML_MEM_TRACE");
- if (breakpoint != NULL) {
- sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
- }
- }
- /**
- * xmlCleanupMemory:
- *
- * DEPRECATED: This function is a no-op. Call xmlCleanupParser
- * to free global state but see the warnings there. xmlCleanupParser
- * should be only called once at program exit. In most cases, you don't
- * have call cleanup functions at all.
- */
- void
- xmlCleanupMemory(void) {
- }
- /**
- * xmlCleanupMemoryInternal:
- *
- * Free up all the memory allocated by the library for its own
- * use. This should not be called by user level code.
- */
- void
- xmlCleanupMemoryInternal(void) {
- /*
- * Don't clean up mutex on Windows. Global state destructors can call
- * malloc functions after xmlCleanupParser was called. If memory
- * debugging is enabled, xmlMemMutex can be used after cleanup.
- *
- * See python/tests/thread2.py
- */
- #if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
- xmlCleanupMutex(&xmlMemMutex);
- #endif
- }
- /**
- * xmlMemSetup:
- * @freeFunc: the free() function to use
- * @mallocFunc: the malloc() function to use
- * @reallocFunc: the realloc() function to use
- * @strdupFunc: the strdup() function to use
- *
- * Override the default memory access functions with a new set
- * This has to be called before any other libxml routines !
- *
- * Should this be blocked if there was already some allocations
- * done ?
- *
- * Returns 0 on success
- */
- int
- xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
- xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
- if (freeFunc == NULL)
- return(-1);
- if (mallocFunc == NULL)
- return(-1);
- if (reallocFunc == NULL)
- return(-1);
- if (strdupFunc == NULL)
- return(-1);
- xmlFree = freeFunc;
- xmlMalloc = mallocFunc;
- xmlMallocAtomic = mallocFunc;
- xmlRealloc = reallocFunc;
- xmlMemStrdup = strdupFunc;
- return(0);
- }
- /**
- * xmlMemGet:
- * @freeFunc: place to save the free() function in use
- * @mallocFunc: place to save the malloc() function in use
- * @reallocFunc: place to save the realloc() function in use
- * @strdupFunc: place to save the strdup() function in use
- *
- * Provides the memory access functions set currently in use
- *
- * Returns 0 on success
- */
- int
- xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
- xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
- if (freeFunc != NULL) *freeFunc = xmlFree;
- if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
- if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
- if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
- return(0);
- }
- /**
- * xmlGcMemSetup:
- * @freeFunc: the free() function to use
- * @mallocFunc: the malloc() function to use
- * @mallocAtomicFunc: the malloc() function to use for atomic allocations
- * @reallocFunc: the realloc() function to use
- * @strdupFunc: the strdup() function to use
- *
- * Override the default memory access functions with a new set
- * This has to be called before any other libxml routines !
- * The mallocAtomicFunc is specialized for atomic block
- * allocations (i.e. of areas useful for garbage collected memory allocators
- *
- * Should this be blocked if there was already some allocations
- * done ?
- *
- * Returns 0 on success
- */
- int
- xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
- xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
- xmlStrdupFunc strdupFunc) {
- if (freeFunc == NULL)
- return(-1);
- if (mallocFunc == NULL)
- return(-1);
- if (mallocAtomicFunc == NULL)
- return(-1);
- if (reallocFunc == NULL)
- return(-1);
- if (strdupFunc == NULL)
- return(-1);
- xmlFree = freeFunc;
- xmlMalloc = mallocFunc;
- xmlMallocAtomic = mallocAtomicFunc;
- xmlRealloc = reallocFunc;
- xmlMemStrdup = strdupFunc;
- return(0);
- }
- /**
- * xmlGcMemGet:
- * @freeFunc: place to save the free() function in use
- * @mallocFunc: place to save the malloc() function in use
- * @mallocAtomicFunc: place to save the atomic malloc() function in use
- * @reallocFunc: place to save the realloc() function in use
- * @strdupFunc: place to save the strdup() function in use
- *
- * Provides the memory access functions set currently in use
- * The mallocAtomicFunc is specialized for atomic block
- * allocations (i.e. of areas useful for garbage collected memory allocators
- *
- * Returns 0 on success
- */
- int
- xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
- xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
- xmlStrdupFunc *strdupFunc) {
- if (freeFunc != NULL) *freeFunc = xmlFree;
- if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
- if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
- if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
- if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
- return(0);
- }
|