📄 xmlmemory.c
字号:
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));
}
/**
* 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) {
return(debugMemBlocks);
}
#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
*/
static void
xmlMemContentShow(FILE *fp, MEMHDR *p)
{
int i,j,len = p->mh_size;
const char *buf = (const char *) HDR_2_CLIENT(p);
if (p == NULL) {
fprintf(fp, " NULL");
return;
}
for (i = 0;i < len;i++) {
if (buf[i] == 0) break;
if (!isprint((unsigned char) buf[i])) break;
}
if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
if (len >= 4) {
MEMHDR *q;
void *cur;
for (j = 0;j < len -3;j += 4) {
cur = *((void **) &buf[j]);
q = CLIENT_2_HDR(cur);
p = memlist;
while (p != NULL) {
if (p == q) break;
p = p->mh_next;
}
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 {
if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
else {
fprintf(fp," [");
for (j = 0;j < i;j++)
fprintf(fp,"%c", buf[j]);
fprintf(fp,"]");
}
}
}
#endif
/**
* 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;
#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
time_t currentTime;
char buf[500];
struct tm * tstruct;
#endif
#endif
FILE *old_fp = fp;
if (fp == NULL) {
fp = fopen(".memorylist", "w");
if (fp == NULL)
return;
}
#ifdef MEM_LIST
#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
currentTime = time(NULL);
tstruct = localtime(¤tTime);
strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
fprintf(fp," %s\n\n", buf);
#endif
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++;
if (nb < 100)
xmlMemContentShow(fp, p);
else
fprintf(fp," skip");
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;
#ifdef MEM_LIST_DEBUG
if (stderr)
Mem_Display(stderr);
#endif
}
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;
#ifdef MEM_LIST_DEBUG
if (stderr)
Mem_Display(stderr);
#endif
}
#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");
xmlMemContentShow(fp, p);
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:
*
* Initialize the memory layer.
*
* Returns 0 on success
*/
int
xmlInitMemory(void)
{
#ifdef HAVE_STDLIB_H
char *breakpoint;
#endif
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlInitMemory()\n");
#endif
/*
This is really not good code (see Bug 130419). Suggestions for
improvement will be welcome!
*/
if (xmlMemInitialized) return(-1);
xmlMemInitialized = 1;
xmlMemMutex = xmlNewMutex();
#ifdef HAVE_STDLIB_H
breakpoint = getenv("XML_MEM_BREAKPOINT");
if (breakpoint != NULL) {
sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
}
#endif
#ifdef HAVE_STDLIB_H
breakpoint = getenv("XML_MEM_TRACE");
if (breakpoint != NULL) {
sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
}
#endif
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlInitMemory() Ok\n");
#endif
return(0);
}
/**
* xmlCleanupMemory:
*
* Free up all the memory allocated by the library for its own
* use. This should not be called by user level code.
*/
void
xmlCleanupMemory(void) {
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlCleanupMemory()\n");
#endif
if (xmlMemInitialized == 0)
return;
xmlFreeMutex(xmlMemMutex);
xmlMemMutex = NULL;
xmlMemInitialized = 0;
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlCleanupMemory() Ok\n");
#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) {
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlMemSetup()\n");
#endif
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;
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlMemSetup() Ok\n");
#endif
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) {
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlGcMemSetup()\n");
#endif
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;
#ifdef DEBUG_MEMORY
xmlGenericError(xmlGenericErrorContext,
"xmlGcMemSetup() Ok\n");
#endif
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);
}
#define bottom_xmlmemory
#include "elfgcchack.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -