/* * xmlmemory.c: libxml memory allocator wrapper. * * daniel@veillard.com */ #define IN_LIBXML#include "libxml.h" #include <string.h> #ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif #ifdef HAVE_TIME_H#include <time.h>#endif #ifdef HAVE_STDLIB_H#include <stdlib.h>#else#ifdef HAVE_MALLOC_H#include <malloc.h>#endif#endif #ifdef HAVE_CTYPE_H#include <ctype.h>#endif /* #define DEBUG_MEMORY */ /** * 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/globals.h> /* must come before xmlmemory.h */#include <libxml/xmlmemory.h>#include <libxml/xmlerror.h>#include <libxml/threads.h> static int xmlMemInitialized = 0;static unsigned long debugMemSize = 0;static unsigned long debugMemBlocks = 0;static unsigned long debugMaxMemSize = 0;static xmlMutexPtr xmlMemMutex = NULL; 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 informations */ #define MEMTAG 0x5aa5 #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 CLIENT_2_HDR(a) ((MEMHDR *) (((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_LISTstatic MEMHDR *memlist = NULL;#endif static void debugmem_tag_error(void *addr);#ifdef MEM_LISTstatic 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. */ voidxmlMallocBreakpoint(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; if (!xmlMemInitialized) xmlInitMemory();#ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d)\n",size);#endif TEST_POINT p = (MEMHDR *) malloc(RESERVE_SIZE+size); if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n"); xmlMemoryDump(); 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); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d) Ok\n",size);#endif 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 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; if (!xmlMemInitialized) xmlInitMemory();#ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d)\n",size);#endif TEST_POINT p = (MEMHDR *) malloc(RESERVE_SIZE+size); if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n"); xmlMemoryDump(); 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); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d) Ok\n",size);#endif 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; unsigned long number;#ifdef DEBUG_MEMORY size_t oldsize;#endif if (ptr == NULL) return(xmlMallocLoc(size, file, line)); if (!xmlMemInitialized) xmlInitMemory(); 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 DEBUG_MEMORY oldsize = p->mh_size;#endif#ifdef MEM_LIST debugmem_list_delete(p);#endif xmlMutexUnlock(xmlMemMutex); p = (MEMHDR *) realloc(p,RESERVE_SIZE+size); if (!p) { goto error; } 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 #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Realloced(%d to %d) Ok\n", oldsize, size);#endif 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. */voidxmlMemFree(void *ptr){ MEMHDR *p; char *target;#ifdef DEBUG_MEMORY size_t size;#endif 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 DEBUG_MEMORY size = p->mh_size;#endif#ifdef MEM_LIST debugmem_list_delete(p);#endif xmlMutexUnlock(xmlMemMutex); free(p); TEST_POINT #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Freed(%d) Ok\n", size);#endif return; error: xmlGenericError(xmlGenericErrorContext, "xmlMemFree(%lX) error\n", (unsigned long) 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; if (!xmlMemInitialized) xmlInitMemory(); TEST_POINT 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;Lines 1–500 of 1123. Load more
/* * xmlmemory.c: libxml memory allocator wrapper. * * daniel@veillard.com */ #define IN_LIBXML #include "libxml.h" #include <string.h> #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif #ifdef HAVE_TIME_H #include <time.h> #endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #else #ifdef HAVE_MALLOC_H #include <malloc.h> #endif #endif #ifdef HAVE_CTYPE_H #include <ctype.h> #endif /* #define DEBUG_MEMORY */ /** * 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/globals.h> /* must come before xmlmemory.h */ #include <libxml/xmlmemory.h> #include <libxml/xmlerror.h> #include <libxml/threads.h> static int xmlMemInitialized = 0; static unsigned long debugMemSize = 0; static unsigned long debugMemBlocks = 0; static unsigned long debugMaxMemSize = 0; static xmlMutexPtr xmlMemMutex = NULL; 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 informations */ #define MEMTAG 0x5aa5 #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 CLIENT_2_HDR(a) ((MEMHDR *) (((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; if (!xmlMemInitialized) xmlInitMemory(); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d)\n",size); #endif TEST_POINT p = (MEMHDR *) malloc(RESERVE_SIZE+size); if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n"); xmlMemoryDump(); 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); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d) Ok\n",size); #endif 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 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; if (!xmlMemInitialized) xmlInitMemory(); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d)\n",size); #endif TEST_POINT p = (MEMHDR *) malloc(RESERVE_SIZE+size); if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n"); xmlMemoryDump(); 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); #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Malloc(%d) Ok\n",size); #endif 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; unsigned long number; #ifdef DEBUG_MEMORY size_t oldsize; #endif if (ptr == NULL) return(xmlMallocLoc(size, file, line)); if (!xmlMemInitialized) xmlInitMemory(); 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 DEBUG_MEMORY oldsize = p->mh_size; #endif #ifdef MEM_LIST debugmem_list_delete(p); #endif xmlMutexUnlock(xmlMemMutex); p = (MEMHDR *) realloc(p,RESERVE_SIZE+size); if (!p) { goto error; } 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 #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Realloced(%d to %d) Ok\n", oldsize, size); #endif 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; #ifdef DEBUG_MEMORY size_t size; #endif 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 DEBUG_MEMORY size = p->mh_size; #endif #ifdef MEM_LIST debugmem_list_delete(p); #endif xmlMutexUnlock(xmlMemMutex); free(p); TEST_POINT #ifdef DEBUG_MEMORY xmlGenericError(xmlGenericErrorContext, "Freed(%d) Ok\n", size); #endif return; error: xmlGenericError(xmlGenericErrorContext, "xmlMemFree(%lX) error\n", (unsigned long) 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; if (!xmlMemInitialized) xmlInitMemory(); TEST_POINT 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;