1123 lines · 25.6 KB · C
RawDownload
/* * 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t