📄 xmlmemory.c.svn-base
字号:
/* * 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/** * 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/globals.h>#include <libxml/xmlerror.h>#include <libxml/threads.h>static int xmlMemInitialized = 0;static unsigned long debugMemSize = 0;static unsigned long debugMaxMemSize = 0;static xmlMutexPtr xmlMemMutex = NULL;void xmlMallocBreakpoint(void);/************************************************************************ * * * Macros, variables and associated types * * * ************************************************************************/#ifdef xmlMalloc#undef xmlMalloc#endif#ifdef xmlRealloc#undef xmlRealloc#endif#ifdef xmlMemStrdup#undef xmlMemStrdup#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 5typedef 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;#endifstatic 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; 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(%d) Ok\n", xmlMemTraceBlockAt, 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; 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(%d) Ok\n", xmlMemTraceBlockAt, 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; if (ptr == NULL) return(xmlMallocLoc(size, file, line)); if (!xmlMemInitialized) xmlInitMemory(); TEST_POINT p = CLIENT_2_HDR(ptr); number = p->mh_number; if (p->mh_tag != MEMTAG) { Mem_Tag_Err(p); goto error; } p->mh_tag = ~MEMTAG; xmlMutexLock(xmlMemMutex); debugMemSize -= p->mh_size;#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(%d -> %d) Ok\n", xmlMemTraceBlockAt, p->mh_size, 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; 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. */voidxmlMemFree(void *ptr){ MEMHDR *p; char *target; 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; } p->mh_tag = ~MEMTAG; memset(target, -1, p->mh_size); xmlMutexLock(xmlMemMutex); debugMemSize -= p->mh_size;#ifdef MEM_LIST debugmem_list_delete(p);#endif xmlMutexUnlock(xmlMemMutex); free(p); TEST_POINT 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; xmlMutexLock(xmlMemMutex); p->mh_number = ++block; debugMemSize += size; 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -