2001-02-23 20:55:21 +03:00
/*
2002-01-01 19:50:03 +03:00
* xmlmemory . c : libxml memory allocator wrapper .
2001-02-23 20:55:21 +03:00
*
2001-06-24 16:13:24 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h>
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
2002-02-10 16:20:39 +03:00
2001-02-23 20:55:21 +03:00
# ifdef HAVE_TIME_H
# include <time.h>
# endif
2002-02-10 16:20:39 +03:00
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# else
2001-02-23 20:55:21 +03:00
# ifdef HAVE_MALLOC_H
# include <malloc.h>
# endif
# endif
2002-02-10 16:20:39 +03:00
2001-02-23 20:55:21 +03:00
# ifdef HAVE_CTYPE_H
# include <ctype.h>
# endif
2004-07-01 16:56:30 +04:00
/* #define DEBUG_MEMORY */
2003-09-28 22:58:27 +04:00
2002-02-06 19:06:58 +03:00
/**
* MEM_LIST :
*
2008-07-30 16:58:11 +04:00
* keep track of all allocated blocks for error reporting
2002-02-06 19:06:58 +03:00
* Always build the memory list !
*/
2003-09-29 14:55:05 +04:00
# ifdef DEBUG_MEMORY_LOCATION
2002-02-06 19:06:58 +03:00
# ifndef MEM_LIST
# define MEM_LIST /* keep a list of all the allocated memory blocks */
# endif
2003-09-29 14:55:05 +04:00
# endif
2001-02-23 20:55:21 +03:00
2004-06-10 17:00:15 +04:00
# include <libxml/globals.h> /* must come before xmlmemory.h */
2001-02-23 20:55:21 +03:00
# include <libxml/xmlmemory.h>
# include <libxml/xmlerror.h>
2003-11-29 13:47:56 +03:00
# include <libxml/threads.h>
2001-02-23 20:55:21 +03:00
2003-09-28 22:58:27 +04:00
static int xmlMemInitialized = 0 ;
2003-09-29 13:22:39 +04:00
static unsigned long debugMemSize = 0 ;
2004-11-02 17:52:23 +03:00
static unsigned long debugMemBlocks = 0 ;
2003-09-29 13:22:39 +04:00
static unsigned long debugMaxMemSize = 0 ;
2003-11-29 13:47:56 +03:00
static xmlMutexPtr xmlMemMutex = NULL ;
2003-09-28 22:58:27 +04:00
2001-03-24 20:00:36 +03:00
void xmlMallocBreakpoint ( void ) ;
/************************************************************************
* *
2012-09-11 09:26:36 +04:00
* Macros , variables and associated types *
2001-03-24 20:00:36 +03:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-10 17:00:15 +04:00
# if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
2001-02-23 20:55:21 +03:00
# ifdef xmlMalloc
# undef xmlMalloc
# endif
# ifdef xmlRealloc
# undef xmlRealloc
# endif
# ifdef xmlMemStrdup
# undef xmlMemStrdup
# endif
2004-06-10 17:00:15 +04:00
# endif
2001-02-23 20:55:21 +03:00
/*
* 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
2003-04-19 04:07:51 +04:00
# define MALLOC_ATOMIC_TYPE 4
# define REALLOC_ATOMIC_TYPE 5
2001-02-23 20:55:21 +03:00
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 )
2016-04-05 22:05:25 +03:00
# define MAX_SIZE_T ((size_t)-1)
2001-02-23 20:55:21 +03:00
2017-06-17 15:13:51 +03:00
# define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
2001-02-23 20:55:21 +03:00
# define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
2003-11-29 13:47:56 +03:00
static unsigned int block = 0 ;
static unsigned int xmlMemStopAtBlock = 0 ;
2001-10-12 02:55:55 +04:00
static void * xmlMemTraceBlockAt = NULL ;
2001-02-23 20:55:21 +03:00
# ifdef MEM_LIST
static MEMHDR * memlist = NULL ;
# endif
2002-12-10 18:19:08 +03:00
static void debugmem_tag_error ( void * addr ) ;
2001-02-23 20:55:21 +03:00
# ifdef MEM_LIST
2002-12-10 18:19:08 +03:00
static void debugmem_list_add ( MEMHDR * ) ;
static void debugmem_list_delete ( MEMHDR * ) ;
2001-02-23 20:55:21 +03:00
# 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 *
2001-07-18 01:38:51 +04:00
xmlMallocLoc ( size_t size , const char * file , int line )
2001-02-23 20:55:21 +03:00
{
MEMHDR * p ;
2001-07-30 17:42:13 +04:00
void * ret ;
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
if ( ! xmlMemInitialized ) xmlInitMemory ( ) ;
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Malloc(%d) \n " , size ) ;
# endif
TEST_POINT
2008-07-30 16:58:11 +04:00
2017-06-06 14:21:14 +03:00
if ( size > ( MAX_SIZE_T - RESERVE_SIZE ) ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlMallocLoc : Unsigned overflow \n " ) ;
xmlMemoryDump ( ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
p = ( MEMHDR * ) malloc ( RESERVE_SIZE + size ) ;
if ( ! p ) {
xmlGenericError ( xmlGenericErrorContext ,
2002-01-01 19:50:03 +03:00
" xmlMallocLoc : Out of free space \n " ) ;
2001-02-23 20:55:21 +03:00
xmlMemoryDump ( ) ;
return ( NULL ) ;
2008-07-30 16:58:11 +04:00
}
2001-02-23 20:55:21 +03:00
p - > mh_tag = MEMTAG ;
p - > mh_size = size ;
p - > mh_type = MALLOC_TYPE ;
p - > mh_file = file ;
p - > mh_line = line ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
p - > mh_number = + + block ;
2001-02-23 20:55:21 +03:00
debugMemSize + = size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks + + ;
2001-02-23 20:55:21 +03:00
if ( debugMemSize > debugMaxMemSize ) debugMaxMemSize = debugMemSize ;
# ifdef MEM_LIST
debugmem_list_add ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Malloc(%d) Ok \n " , size ) ;
# endif
2008-07-30 16:58:11 +04:00
2003-11-29 13:47:56 +03:00
if ( xmlMemStopAtBlock = = p - > mh_number ) xmlMallocBreakpoint ( ) ;
2001-02-23 20:55:21 +03:00
2001-07-30 17:42:13 +04:00
ret = HDR_2_CLIENT ( p ) ;
if ( xmlMemTraceBlockAt = = ret ) {
xmlGenericError ( xmlGenericErrorContext ,
2011-05-06 18:40:10 +04:00
" %p : Malloc(%lu) Ok \n " , xmlMemTraceBlockAt ,
( long unsigned ) size ) ;
2001-07-30 17:42:13 +04:00
xmlMallocBreakpoint ( ) ;
}
2001-02-23 20:55:21 +03:00
TEST_POINT
2001-07-30 17:42:13 +04:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-04-19 04:07:51 +04:00
/**
* xmlMallocAtomicLoc :
2016-04-05 22:05:25 +03:00
* @ size : an unsigned int specifying the size in byte to allocate .
2003-04-19 04:07:51 +04:00
* @ 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 ;
2008-07-30 16:58:11 +04:00
2003-04-19 04:07:51 +04:00
if ( ! xmlMemInitialized ) xmlInitMemory ( ) ;
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Malloc(%d) \n " , size ) ;
# endif
TEST_POINT
2008-07-30 16:58:11 +04:00
2016-04-05 22:05:25 +03:00
if ( size > ( MAX_SIZE_T - RESERVE_SIZE ) ) {
xmlGenericError ( xmlGenericErrorContext ,
2017-06-11 18:12:21 +03:00
" xmlMallocAtomicLoc : Unsigned overflow \n " ) ;
2016-04-05 22:05:25 +03:00
xmlMemoryDump ( ) ;
return ( NULL ) ;
}
2003-04-19 04:07:51 +04:00
p = ( MEMHDR * ) malloc ( RESERVE_SIZE + size ) ;
if ( ! p ) {
xmlGenericError ( xmlGenericErrorContext ,
2016-04-05 22:05:25 +03:00
" xmlMallocAtomicLoc : Out of free space \n " ) ;
2003-04-19 04:07:51 +04:00
xmlMemoryDump ( ) ;
return ( NULL ) ;
2008-07-30 16:58:11 +04:00
}
2003-04-19 04:07:51 +04:00
p - > mh_tag = MEMTAG ;
p - > mh_size = size ;
p - > mh_type = MALLOC_ATOMIC_TYPE ;
p - > mh_file = file ;
p - > mh_line = line ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
p - > mh_number = + + block ;
2003-04-19 04:07:51 +04:00
debugMemSize + = size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks + + ;
2003-04-19 04:07:51 +04:00
if ( debugMemSize > debugMaxMemSize ) debugMaxMemSize = debugMemSize ;
# ifdef MEM_LIST
debugmem_list_add ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2003-04-19 04:07:51 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Malloc(%d) Ok \n " , size ) ;
# endif
2008-07-30 16:58:11 +04:00
2003-11-29 13:47:56 +03:00
if ( xmlMemStopAtBlock = = p - > mh_number ) xmlMallocBreakpoint ( ) ;
2003-04-19 04:07:51 +04:00
ret = HDR_2_CLIENT ( p ) ;
if ( xmlMemTraceBlockAt = = ret ) {
xmlGenericError ( xmlGenericErrorContext ,
2011-05-06 18:40:10 +04:00
" %p : Malloc(%lu) Ok \n " , xmlMemTraceBlockAt ,
( long unsigned ) size ) ;
2003-04-19 04:07:51 +04:00
xmlMallocBreakpoint ( ) ;
}
TEST_POINT
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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 *
2001-07-18 01:38:51 +04:00
xmlMemMalloc ( size_t size )
2001-02-23 20:55:21 +03:00
{
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 *
2001-07-18 01:38:51 +04:00
xmlReallocLoc ( void * ptr , size_t size , const char * file , int line )
2001-02-23 20:55:21 +03:00
{
2014-10-10 14:23:09 +04:00
MEMHDR * p , * tmp ;
2001-02-23 20:55:21 +03:00
unsigned long number ;
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
size_t oldsize ;
# endif
2001-02-23 20:55:21 +03:00
2003-04-24 20:06:47 +04:00
if ( ptr = = NULL )
2004-01-23 01:20:31 +03:00
return ( xmlMallocLoc ( size , file , line ) ) ;
if ( ! xmlMemInitialized ) xmlInitMemory ( ) ;
2001-02-23 20:55:21 +03:00
TEST_POINT
p = CLIENT_2_HDR ( ptr ) ;
number = p - > mh_number ;
2005-04-14 21:50:59 +04:00
if ( xmlMemStopAtBlock = = number ) xmlMallocBreakpoint ( ) ;
2001-02-23 20:55:21 +03:00
if ( p - > mh_tag ! = MEMTAG ) {
Mem_Tag_Err ( p ) ;
goto error ;
}
p - > mh_tag = ~ MEMTAG ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
debugMemSize - = p - > mh_size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks - - ;
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
oldsize = p - > mh_size ;
# endif
2001-02-23 20:55:21 +03:00
# ifdef MEM_LIST
debugmem_list_delete ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2008-07-30 16:58:11 +04:00
2017-06-06 14:21:14 +03:00
if ( size > ( MAX_SIZE_T - RESERVE_SIZE ) ) {
xmlGenericError ( xmlGenericErrorContext ,
2017-06-11 18:12:21 +03:00
" xmlReallocLoc : Unsigned overflow \n " ) ;
2017-06-06 14:21:14 +03:00
xmlMemoryDump ( ) ;
return ( NULL ) ;
}
2014-10-10 14:23:09 +04:00
tmp = ( MEMHDR * ) realloc ( p , RESERVE_SIZE + size ) ;
if ( ! tmp ) {
free ( p ) ;
2001-02-23 20:55:21 +03:00
goto error ;
}
2014-10-10 14:23:09 +04:00
p = tmp ;
2001-07-30 17:42:13 +04:00
if ( xmlMemTraceBlockAt = = ptr ) {
xmlGenericError ( xmlGenericErrorContext ,
2011-05-06 18:40:10 +04:00
" %p : Realloced(%lu -> %lu) Ok \n " ,
xmlMemTraceBlockAt , ( long unsigned ) p - > mh_size ,
( long unsigned ) size ) ;
2001-07-30 17:42:13 +04:00
xmlMallocBreakpoint ( ) ;
}
2001-02-23 20:55:21 +03:00
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 ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
debugMemSize + = size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks + + ;
2001-02-23 20:55:21 +03:00
if ( debugMemSize > debugMaxMemSize ) debugMaxMemSize = debugMemSize ;
# ifdef MEM_LIST
debugmem_list_add ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
TEST_POINT
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Realloced(%d to %d) Ok \n " , oldsize , size ) ;
# endif
2001-02-23 20:55:21 +03:00
return ( HDR_2_CLIENT ( p ) ) ;
2008-07-30 16:58:11 +04:00
error :
2001-02-23 20:55:21 +03:00
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 *
2001-07-18 01:38:51 +04:00
xmlMemRealloc ( void * ptr , size_t size ) {
2001-02-23 20:55:21 +03:00
return ( xmlReallocLoc ( ptr , size , " none " , 0 ) ) ;
}
/**
* xmlMemFree :
* @ ptr : the memory block pointer
*
* a free ( ) equivalent , with error checking .
*/
void
xmlMemFree ( void * ptr )
{
MEMHDR * p ;
2001-03-27 16:47:33 +04:00
char * target ;
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
size_t size ;
# endif
2001-02-23 20:55:21 +03:00
2007-10-30 23:24:40 +03:00
if ( ptr = = NULL )
return ;
2001-07-30 17:42:13 +04:00
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 ( ) ;
}
2001-02-23 20:55:21 +03:00
TEST_POINT
2001-03-27 16:47:33 +04:00
target = ( char * ) ptr ;
2001-02-23 20:55:21 +03:00
p = CLIENT_2_HDR ( ptr ) ;
if ( p - > mh_tag ! = MEMTAG ) {
2001-07-30 17:42:13 +04:00
Mem_Tag_Err ( p ) ;
goto error ;
2001-02-23 20:55:21 +03:00
}
2005-04-14 21:50:59 +04:00
if ( xmlMemStopAtBlock = = p - > mh_number ) xmlMallocBreakpoint ( ) ;
2001-02-23 20:55:21 +03:00
p - > mh_tag = ~ MEMTAG ;
2001-03-27 16:47:33 +04:00
memset ( target , - 1 , p - > mh_size ) ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
debugMemSize - = p - > mh_size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks - - ;
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
size = p - > mh_size ;
# endif
2001-02-23 20:55:21 +03:00
# ifdef MEM_LIST
debugmem_list_delete ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
free ( p ) ;
TEST_POINT
2004-07-02 16:23:44 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" Freed(%d) Ok \n " , size ) ;
# endif
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
return ;
2008-07-30 16:58:11 +04:00
error :
2001-02-23 20:55:21 +03:00
xmlGenericError ( xmlGenericErrorContext ,
2017-10-09 14:37:42 +03:00
" xmlMemFree(%p) error \n " , ptr ) ;
2001-07-30 17:42:13 +04:00
xmlMallocBreakpoint ( ) ;
2001-02-23 20:55:21 +03:00
return ;
}
/**
* xmlMemStrdupLoc :
2002-01-22 21:15:52 +03:00
* @ str : the initial string pointer
2001-02-23 20:55:21 +03:00
* @ file : the file name or NULL
* @ line : the line number
*
* a strdup ( ) equivalent , with logging of the allocation info .
*
2002-01-01 19:50:03 +03:00
* Returns a pointer to the new string or NULL if allocation error occurred .
2001-02-23 20:55:21 +03:00
*/
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
2017-06-06 14:21:14 +03:00
if ( size > ( MAX_SIZE_T - RESERVE_SIZE ) ) {
xmlGenericError ( xmlGenericErrorContext ,
2017-06-11 18:12:21 +03:00
" xmlMemStrdupLoc : Unsigned overflow \n " ) ;
2017-06-06 14:21:14 +03:00
xmlMemoryDump ( ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
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 ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
p - > mh_number = + + block ;
2001-02-23 20:55:21 +03:00
debugMemSize + = size ;
2004-11-02 17:52:23 +03:00
debugMemBlocks + + ;
2001-02-23 20:55:21 +03:00
if ( debugMemSize > debugMaxMemSize ) debugMaxMemSize = debugMemSize ;
# ifdef MEM_LIST
debugmem_list_add ( p ) ;
# endif
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
s = ( char * ) HDR_2_CLIENT ( p ) ;
2008-07-30 16:58:11 +04:00
2003-11-29 13:47:56 +03:00
if ( xmlMemStopAtBlock = = p - > mh_number ) xmlMallocBreakpoint ( ) ;
2001-02-23 20:55:21 +03:00
2014-07-26 17:14:53 +04:00
strcpy ( s , str ) ;
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
TEST_POINT
2001-07-30 17:42:13 +04:00
if ( xmlMemTraceBlockAt = = s ) {
xmlGenericError ( xmlGenericErrorContext ,
" %p : Strdup() Ok \n " , xmlMemTraceBlockAt ) ;
xmlMallocBreakpoint ( ) ;
}
2001-02-23 20:55:21 +03:00
return ( s ) ;
error :
return ( NULL ) ;
}
/**
* xmlMemoryStrdup :
2002-12-10 18:19:08 +03:00
* @ str : the initial string pointer
2001-02-23 20:55:21 +03:00
*
* a strdup ( ) equivalent , with logging of the allocation info .
*
2002-01-01 19:50:03 +03:00
* Returns a pointer to the new string or NULL if allocation error occurred .
2001-02-23 20:55:21 +03:00
*/
char *
xmlMemoryStrdup ( const char * str ) {
return ( xmlMemStrdupLoc ( str , " none " , 0 ) ) ;
}
/**
* xmlMemUsed :
*
2002-12-11 17:23:49 +03:00
* Provides the amount of memory currently allocated
2001-02-23 20:55:21 +03:00
*
* Returns an int representing the amount of memory allocated .
*/
int
xmlMemUsed ( void ) {
2015-04-13 11:32:14 +03:00
int res ;
xmlMutexLock ( xmlMemMutex ) ;
res = debugMemSize ;
xmlMutexUnlock ( xmlMemMutex ) ;
return ( res ) ;
2001-02-23 20:55:21 +03:00
}
2004-11-02 17:52:23 +03:00
/**
* xmlMemBlocks :
*
* Provides the number of memory areas currently allocated
*
* Returns an int representing the number of blocks
*/
int
xmlMemBlocks ( void ) {
2015-04-13 11:32:14 +03:00
int res ;
xmlMutexLock ( xmlMemMutex ) ;
res = debugMemBlocks ;
xmlMutexUnlock ( xmlMemMutex ) ;
return ( res ) ;
2004-11-02 17:52:23 +03:00
}
2001-02-23 20:55:21 +03:00
# ifdef MEM_LIST
/**
* xmlMemContentShow :
* @ fp : a FILE descriptor used as the output file
* @ p : a memory block header
*
* tries to show some content from the memory block
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlMemContentShow ( FILE * fp , MEMHDR * p )
{
2014-05-09 13:00:08 +04:00
int i , j , k , len ;
const char * buf ;
2001-02-23 20:55:21 +03:00
if ( p = = NULL ) {
fprintf ( fp , " NULL " ) ;
return ;
}
2014-05-09 13:00:08 +04:00
len = p - > mh_size ;
buf = ( const char * ) HDR_2_CLIENT ( p ) ;
2001-02-23 20:55:21 +03:00
for ( i = 0 ; i < len ; i + + ) {
if ( buf [ i ] = = 0 ) break ;
2002-02-15 23:48:08 +03:00
if ( ! isprint ( ( unsigned char ) buf [ i ] ) ) break ;
2001-02-23 20:55:21 +03:00
}
if ( ( i < 4 ) & & ( ( buf [ i ] ! = 0 ) | | ( i = = 0 ) ) ) {
if ( len > = 4 ) {
MEMHDR * q ;
void * cur ;
2006-10-12 01:12:10 +04:00
for ( j = 0 ; ( j < len - 3 ) & & ( j < 40 ) ; j + = 4 ) {
2001-02-23 20:55:21 +03:00
cur = * ( ( void * * ) & buf [ j ] ) ;
q = CLIENT_2_HDR ( cur ) ;
p = memlist ;
2006-10-12 01:12:10 +04:00
k = 0 ;
2001-02-23 20:55:21 +03:00
while ( p ! = NULL ) {
if ( p = = q ) break ;
p = p - > mh_next ;
2006-10-12 01:12:10 +04:00
if ( k + + > 100 ) break ;
2001-02-23 20:55:21 +03:00
}
if ( ( p ! = NULL ) & & ( p = = q ) ) {
fprintf ( fp , " pointer to #%lu at index %d " ,
p - > mh_number , j ) ;
return ;
}
}
}
} else if ( ( i = = 0 ) & & ( buf [ i ] = = 0 ) ) {
fprintf ( fp , " null " ) ;
} else {
2008-07-30 16:58:11 +04:00
if ( buf [ i ] = = 0 ) fprintf ( fp , " \" %.25s \" " , buf ) ;
2001-02-23 20:55:21 +03:00
else {
fprintf ( fp , " [ " ) ;
for ( j = 0 ; j < i ; j + + )
fprintf ( fp , " %c " , buf [ j ] ) ;
fprintf ( fp , " ] " ) ;
}
}
}
# endif
2008-07-30 16:58:11 +04:00
/**
* 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 + + ;
if ( nb < 100 )
xmlMemContentShow ( fp , p ) ;
else
fprintf ( fp , " skip " ) ;
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 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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 ;
2002-02-14 00:14:46 +03:00
unsigned idx ;
2001-07-30 17:42:13 +04:00
int nb = 0 ;
2001-02-23 20:55:21 +03:00
# if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
time_t currentTime ;
char buf [ 500 ] ;
struct tm * tstruct ;
2005-05-08 15:39:56 +04:00
# endif
# endif
FILE * old_fp = fp ;
if ( fp = = NULL ) {
fp = fopen ( " .memorylist " , " w " ) ;
if ( fp = = NULL )
return ;
}
2001-02-23 20:55:21 +03:00
2005-05-08 15:39:56 +04:00
# ifdef MEM_LIST
# if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
2001-02-23 20:55:21 +03:00
currentTime = time ( NULL ) ;
tstruct = localtime ( & currentTime ) ;
2001-03-24 20:00:36 +03:00
strftime ( buf , sizeof ( buf ) - 1 , " %I:%M:%S %p " , tstruct ) ;
2001-02-23 20:55:21 +03:00
fprintf ( fp , " %s \n \n " , buf ) ;
# endif
2008-07-30 16:58:11 +04:00
2001-02-23 20:55:21 +03:00
fprintf ( fp , " MEMORY ALLOCATED : %lu, MAX was %lu \n " ,
debugMemSize , debugMaxMemSize ) ;
fprintf ( fp , " BLOCK NUMBER SIZE TYPE \n " ) ;
idx = 0 ;
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
p = memlist ;
while ( p ) {
2002-02-14 00:14:46 +03:00
fprintf ( fp , " %-5u %6lu %6lu " , idx + + , p - > mh_number ,
( unsigned long ) p - > mh_size ) ;
2001-02-23 20:55:21 +03:00
switch ( p - > mh_type ) {
case STRDUP_TYPE : fprintf ( fp , " strdup() in " ) ; break ;
case MALLOC_TYPE : fprintf ( fp , " malloc() in " ) ; break ;
2004-07-02 16:23:44 +04:00
case REALLOC_TYPE : fprintf ( fp , " realloc() in " ) ; break ;
2003-04-19 04:07:51 +04:00
case MALLOC_ATOMIC_TYPE : fprintf ( fp , " atomicmalloc() in " ) ; break ;
2004-07-02 16:23:44 +04:00
case REALLOC_ATOMIC_TYPE : fprintf ( fp , " atomicrealloc() in " ) ; break ;
default :
2004-09-18 08:52:08 +04:00
fprintf ( fp , " Unknown memory block, may be corrupted " ) ;
2004-07-02 16:23:44 +04:00
xmlMutexUnlock ( xmlMemMutex ) ;
2005-05-08 15:39:56 +04:00
if ( old_fp = = NULL )
fclose ( fp ) ;
2004-07-02 16:23:44 +04:00
return ;
2001-02-23 20:55:21 +03:00
}
2004-09-18 08:52:08 +04:00
if ( p - > mh_file ! = NULL ) fprintf ( fp , " %s(%u) " , p - > mh_file , p - > mh_line ) ;
2001-02-23 20:55:21 +03:00
if ( p - > mh_tag ! = MEMTAG )
fprintf ( fp , " INVALID " ) ;
2001-07-30 17:42:13 +04:00
nb + + ;
if ( nb < 100 )
xmlMemContentShow ( fp , p ) ;
else
fprintf ( fp , " skip " ) ;
2001-02-23 20:55:21 +03:00
fprintf ( fp , " \n " ) ;
p = p - > mh_next ;
}
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2001-02-23 20:55:21 +03:00
# else
fprintf ( fp , " Memory list not compiled (MEM_LIST not defined !) \n " ) ;
# endif
2005-05-08 15:39:56 +04:00
if ( old_fp = = NULL )
fclose ( fp ) ;
2001-02-23 20:55:21 +03:00
}
# ifdef MEM_LIST
2002-12-10 18:19:08 +03:00
static void debugmem_list_add ( MEMHDR * p )
2001-02-23 20:55:21 +03:00
{
p - > mh_next = memlist ;
p - > mh_prev = NULL ;
if ( memlist ) memlist - > mh_prev = p ;
memlist = p ;
# ifdef MEM_LIST_DEBUG
if ( stderr )
Mem_Display ( stderr ) ;
# endif
}
2002-12-10 18:19:08 +03:00
static void debugmem_list_delete ( MEMHDR * p )
2001-02-23 20:55:21 +03:00
{
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 ;
# ifdef MEM_LIST_DEBUG
if ( stderr )
Mem_Display ( stderr ) ;
# endif
}
# endif
/*
2002-12-10 18:19:08 +03:00
* debugmem_tag_error :
*
* internal error function .
2001-02-23 20:55:21 +03:00
*/
2008-07-30 16:58:11 +04:00
2002-12-10 18:19:08 +03:00
static void debugmem_tag_error ( void * p )
2001-02-23 20:55:21 +03:00
{
xmlGenericError ( xmlGenericErrorContext ,
" Memory tag error occurs :%p \n \t bye \n " , p ) ;
# ifdef MEM_LIST
if ( stderr )
xmlMemDisplay ( stderr ) ;
# endif
}
2003-09-29 17:20:24 +04:00
# ifdef MEM_LIST
2001-10-12 02:55:55 +04:00
static FILE * xmlMemoryDumpFile = NULL ;
2003-09-29 17:20:24 +04:00
# endif
2001-02-23 20:55:21 +03:00
2003-09-29 13:22:39 +04:00
/**
* 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
2003-09-29 14:55:05 +04:00
xmlMemShow ( FILE * fp , int nr ATTRIBUTE_UNUSED )
2003-09-29 13:22:39 +04:00
{
# ifdef MEM_LIST
MEMHDR * p ;
# endif
if ( fp ! = NULL )
fprintf ( fp , " MEMORY ALLOCATED : %lu, MAX was %lu \n " ,
debugMemSize , debugMaxMemSize ) ;
# ifdef MEM_LIST
2003-11-29 13:47:56 +03:00
xmlMutexLock ( xmlMemMutex ) ;
2003-09-29 13:22:39 +04:00
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 )
2004-09-18 08:52:08 +04:00
fprintf ( fp , " %s(%u) " , p - > mh_file , p - > mh_line ) ;
2003-09-29 13:22:39 +04:00
if ( p - > mh_tag ! = MEMTAG )
fprintf ( fp , " INVALID " ) ;
xmlMemContentShow ( fp , p ) ;
fprintf ( fp , " \n " ) ;
nr - - ;
p = p - > mh_next ;
}
}
2003-11-29 13:47:56 +03:00
xmlMutexUnlock ( xmlMemMutex ) ;
2008-07-30 16:58:11 +04:00
# endif /* MEM_LIST */
2003-09-29 13:22:39 +04:00
}
2001-02-23 20:55:21 +03:00
/**
* xmlMemoryDump :
*
* Dump in - extenso the memory blocks allocated to the file . memorylist
*/
void
xmlMemoryDump ( void )
{
2003-09-29 14:55:05 +04:00
# ifdef MEM_LIST
2001-02-23 20:55:21 +03:00
FILE * dump ;
2002-03-18 21:36:20 +03:00
if ( debugMaxMemSize = = 0 )
return ;
2001-02-23 20:55:21 +03:00
dump = fopen ( " .memdump " , " w " ) ;
2001-11-22 21:20:37 +03:00
if ( dump = = NULL )
xmlMemoryDumpFile = stderr ;
2001-02-23 20:55:21 +03:00
else xmlMemoryDumpFile = dump ;
xmlMemDisplay ( xmlMemoryDumpFile ) ;
if ( dump ! = NULL ) fclose ( dump ) ;
2003-09-29 14:55:05 +04:00
# endif /* MEM_LIST */
2001-02-23 20:55:21 +03:00
}
/****************************************************************
* *
* Initialization Routines *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlInitMemory :
*
* Initialize the memory layer .
*
* Returns 0 on success
*/
int
xmlInitMemory ( void )
{
2004-07-13 19:25:08 +04:00
# ifdef HAVE_STDLIB_H
char * breakpoint ;
2008-07-30 16:58:11 +04:00
# endif
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlInitMemory() \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2004-01-04 04:01:14 +03:00
/*
This is really not good code ( see Bug 130419 ) . Suggestions for
improvement will be welcome !
*/
if ( xmlMemInitialized ) return ( - 1 ) ;
2003-11-29 13:47:56 +03:00
xmlMemInitialized = 1 ;
xmlMemMutex = xmlNewMutex ( ) ;
2001-02-23 20:55:21 +03:00
# ifdef HAVE_STDLIB_H
breakpoint = getenv ( " XML_MEM_BREAKPOINT " ) ;
if ( breakpoint ! = NULL ) {
2003-11-29 13:47:56 +03:00
sscanf ( breakpoint , " %ud " , & xmlMemStopAtBlock ) ;
2001-02-23 20:55:21 +03:00
}
2008-07-30 16:58:11 +04:00
# endif
2001-07-30 17:42:13 +04:00
# ifdef HAVE_STDLIB_H
breakpoint = getenv ( " XML_MEM_TRACE " ) ;
if ( breakpoint ! = NULL ) {
sscanf ( breakpoint , " %p " , & xmlMemTraceBlockAt ) ;
}
2008-07-30 16:58:11 +04:00
# endif
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlInitMemory() Ok \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2003-09-28 22:58:27 +04:00
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
2003-12-30 11:30:19 +03:00
/**
* xmlCleanupMemory :
*
2004-12-10 13:26:42 +03:00
* Free up all the memory allocated by the library for its own
* use . This should not be called by user level code .
2003-12-30 11:30:19 +03:00
*/
void
xmlCleanupMemory ( void ) {
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlCleanupMemory() \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2003-12-30 11:30:19 +03:00
if ( xmlMemInitialized = = 0 )
return ;
xmlFreeMutex ( xmlMemMutex ) ;
2004-01-02 13:42:01 +03:00
xmlMemMutex = NULL ;
2003-12-30 11:30:19 +03:00
xmlMemInitialized = 0 ;
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlCleanupMemory() Ok \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2003-12-30 11:30:19 +03:00
}
2001-02-23 20:55:21 +03:00
/**
* 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 ) {
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlMemSetup() \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2001-02-23 20:55:21 +03:00
if ( freeFunc = = NULL )
return ( - 1 ) ;
if ( mallocFunc = = NULL )
return ( - 1 ) ;
if ( reallocFunc = = NULL )
return ( - 1 ) ;
if ( strdupFunc = = NULL )
return ( - 1 ) ;
xmlFree = freeFunc ;
xmlMalloc = mallocFunc ;
2003-04-19 04:07:51 +04:00
xmlMallocAtomic = mallocFunc ;
2001-02-23 20:55:21 +03:00
xmlRealloc = reallocFunc ;
xmlMemStrdup = strdupFunc ;
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlMemSetup() Ok \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/**
* xmlMemGet :
2002-12-11 17:23:49 +03:00
* @ 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
2001-02-23 20:55:21 +03:00
*
2002-12-11 17:23:49 +03:00
* Provides the memory access functions set currently in use
2001-02-23 20:55:21 +03:00
*
* 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 ) ;
}
2003-04-19 04:07:51 +04:00
/**
* 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 ) {
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlGcMemSetup() \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2003-04-19 04:07:51 +04:00
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 ;
2004-07-01 16:56:30 +04:00
# ifdef DEBUG_MEMORY
xmlGenericError ( xmlGenericErrorContext ,
" xmlGcMemSetup() Ok \n " ) ;
2008-07-30 16:58:11 +04:00
# endif
2003-04-19 04:07:51 +04:00
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 ) ;
}
2005-04-01 17:11:58 +04:00
# define bottom_xmlmemory
# include "elfgcchack.h"