Annotation of embedaddon/libxml2/xmlmemory.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * xmlmemory.c:  libxml memory allocator wrapper.
        !             3:  *
        !             4:  * daniel@veillard.com
        !             5:  */
        !             6: 
        !             7: #define IN_LIBXML
        !             8: #include "libxml.h"
        !             9: 
        !            10: #include <string.h>
        !            11: 
        !            12: #ifdef HAVE_SYS_TYPES_H
        !            13: #include <sys/types.h>
        !            14: #endif
        !            15: 
        !            16: #ifdef HAVE_TIME_H
        !            17: #include <time.h>
        !            18: #endif
        !            19: 
        !            20: #ifdef HAVE_STDLIB_H
        !            21: #include <stdlib.h>
        !            22: #else
        !            23: #ifdef HAVE_MALLOC_H
        !            24: #include <malloc.h>
        !            25: #endif
        !            26: #endif
        !            27: 
        !            28: #ifdef HAVE_CTYPE_H
        !            29: #include <ctype.h>
        !            30: #endif
        !            31: 
        !            32: /* #define DEBUG_MEMORY */
        !            33: 
        !            34: /**
        !            35:  * MEM_LIST:
        !            36:  *
        !            37:  * keep track of all allocated blocks for error reporting
        !            38:  * Always build the memory list !
        !            39:  */
        !            40: #ifdef DEBUG_MEMORY_LOCATION
        !            41: #ifndef MEM_LIST
        !            42: #define MEM_LIST /* keep a list of all the allocated memory blocks */
        !            43: #endif
        !            44: #endif
        !            45: 
        !            46: #include <libxml/globals.h>    /* must come before xmlmemory.h */
        !            47: #include <libxml/xmlmemory.h>
        !            48: #include <libxml/xmlerror.h>
        !            49: #include <libxml/threads.h>
        !            50: 
        !            51: static int xmlMemInitialized = 0;
        !            52: static unsigned long  debugMemSize = 0;
        !            53: static unsigned long  debugMemBlocks = 0;
        !            54: static unsigned long  debugMaxMemSize = 0;
        !            55: static xmlMutexPtr xmlMemMutex = NULL;
        !            56: 
        !            57: void xmlMallocBreakpoint(void);
        !            58: 
        !            59: /************************************************************************
        !            60:  *                                                                     *
        !            61:  *             Macros, variables and associated types                  *
        !            62:  *                                                                     *
        !            63:  ************************************************************************/
        !            64: 
        !            65: #if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
        !            66: #ifdef xmlMalloc
        !            67: #undef xmlMalloc
        !            68: #endif
        !            69: #ifdef xmlRealloc
        !            70: #undef xmlRealloc
        !            71: #endif
        !            72: #ifdef xmlMemStrdup
        !            73: #undef xmlMemStrdup
        !            74: #endif
        !            75: #endif
        !            76: 
        !            77: /*
        !            78:  * Each of the blocks allocated begin with a header containing informations
        !            79:  */
        !            80: 
        !            81: #define MEMTAG 0x5aa5
        !            82: 
        !            83: #define MALLOC_TYPE 1
        !            84: #define REALLOC_TYPE 2
        !            85: #define STRDUP_TYPE 3
        !            86: #define MALLOC_ATOMIC_TYPE 4
        !            87: #define REALLOC_ATOMIC_TYPE 5
        !            88: 
        !            89: typedef struct memnod {
        !            90:     unsigned int   mh_tag;
        !            91:     unsigned int   mh_type;
        !            92:     unsigned long  mh_number;
        !            93:     size_t         mh_size;
        !            94: #ifdef MEM_LIST
        !            95:    struct memnod *mh_next;
        !            96:    struct memnod *mh_prev;
        !            97: #endif
        !            98:    const char    *mh_file;
        !            99:    unsigned int   mh_line;
        !           100: }  MEMHDR;
        !           101: 
        !           102: 
        !           103: #ifdef SUN4
        !           104: #define ALIGN_SIZE  16
        !           105: #else
        !           106: #define ALIGN_SIZE  sizeof(double)
        !           107: #endif
        !           108: #define HDR_SIZE    sizeof(MEMHDR)
        !           109: #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
        !           110:                      / ALIGN_SIZE ) * ALIGN_SIZE)
        !           111: 
        !           112: 
        !           113: #define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
        !           114: #define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
        !           115: 
        !           116: 
        !           117: static unsigned int block=0;
        !           118: static unsigned int xmlMemStopAtBlock = 0;
        !           119: static void *xmlMemTraceBlockAt = NULL;
        !           120: #ifdef MEM_LIST
        !           121: static MEMHDR *memlist = NULL;
        !           122: #endif
        !           123: 
        !           124: static void debugmem_tag_error(void *addr);
        !           125: #ifdef MEM_LIST
        !           126: static void  debugmem_list_add(MEMHDR *);
        !           127: static void debugmem_list_delete(MEMHDR *);
        !           128: #endif
        !           129: #define Mem_Tag_Err(a) debugmem_tag_error(a);
        !           130: 
        !           131: #ifndef TEST_POINT
        !           132: #define TEST_POINT
        !           133: #endif
        !           134: 
        !           135: /**
        !           136:  * xmlMallocBreakpoint:
        !           137:  *
        !           138:  * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
        !           139:  * number reaches the specified value this function is called. One need to add a breakpoint
        !           140:  * to it to get the context in which the given block is allocated.
        !           141:  */
        !           142: 
        !           143: void
        !           144: xmlMallocBreakpoint(void) {
        !           145:     xmlGenericError(xmlGenericErrorContext,
        !           146:            "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
        !           147: }
        !           148: 
        !           149: /**
        !           150:  * xmlMallocLoc:
        !           151:  * @size:  an int specifying the size in byte to allocate.
        !           152:  * @file:  the file name or NULL
        !           153:  * @line:  the line number
        !           154:  *
        !           155:  * a malloc() equivalent, with logging of the allocation info.
        !           156:  *
        !           157:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
        !           158:  */
        !           159: 
        !           160: void *
        !           161: xmlMallocLoc(size_t size, const char * file, int line)
        !           162: {
        !           163:     MEMHDR *p;
        !           164:     void *ret;
        !           165: 
        !           166:     if (!xmlMemInitialized) xmlInitMemory();
        !           167: #ifdef DEBUG_MEMORY
        !           168:     xmlGenericError(xmlGenericErrorContext,
        !           169:            "Malloc(%d)\n",size);
        !           170: #endif
        !           171: 
        !           172:     TEST_POINT
        !           173: 
        !           174:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
        !           175: 
        !           176:     if (!p) {
        !           177:        xmlGenericError(xmlGenericErrorContext,
        !           178:                "xmlMallocLoc : Out of free space\n");
        !           179:        xmlMemoryDump();
        !           180:        return(NULL);
        !           181:     }
        !           182:     p->mh_tag = MEMTAG;
        !           183:     p->mh_size = size;
        !           184:     p->mh_type = MALLOC_TYPE;
        !           185:     p->mh_file = file;
        !           186:     p->mh_line = line;
        !           187:     xmlMutexLock(xmlMemMutex);
        !           188:     p->mh_number = ++block;
        !           189:     debugMemSize += size;
        !           190:     debugMemBlocks++;
        !           191:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
        !           192: #ifdef MEM_LIST
        !           193:     debugmem_list_add(p);
        !           194: #endif
        !           195:     xmlMutexUnlock(xmlMemMutex);
        !           196: 
        !           197: #ifdef DEBUG_MEMORY
        !           198:     xmlGenericError(xmlGenericErrorContext,
        !           199:            "Malloc(%d) Ok\n",size);
        !           200: #endif
        !           201: 
        !           202:     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
        !           203: 
        !           204:     ret = HDR_2_CLIENT(p);
        !           205: 
        !           206:     if (xmlMemTraceBlockAt == ret) {
        !           207:        xmlGenericError(xmlGenericErrorContext,
        !           208:                        "%p : Malloc(%ld) Ok\n", xmlMemTraceBlockAt, size);
        !           209:        xmlMallocBreakpoint();
        !           210:     }
        !           211: 
        !           212:     TEST_POINT
        !           213: 
        !           214:     return(ret);
        !           215: }
        !           216: 
        !           217: /**
        !           218:  * xmlMallocAtomicLoc:
        !           219:  * @size:  an int specifying the size in byte to allocate.
        !           220:  * @file:  the file name or NULL
        !           221:  * @line:  the line number
        !           222:  *
        !           223:  * a malloc() equivalent, with logging of the allocation info.
        !           224:  *
        !           225:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
        !           226:  */
        !           227: 
        !           228: void *
        !           229: xmlMallocAtomicLoc(size_t size, const char * file, int line)
        !           230: {
        !           231:     MEMHDR *p;
        !           232:     void *ret;
        !           233: 
        !           234:     if (!xmlMemInitialized) xmlInitMemory();
        !           235: #ifdef DEBUG_MEMORY
        !           236:     xmlGenericError(xmlGenericErrorContext,
        !           237:            "Malloc(%d)\n",size);
        !           238: #endif
        !           239: 
        !           240:     TEST_POINT
        !           241: 
        !           242:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
        !           243: 
        !           244:     if (!p) {
        !           245:        xmlGenericError(xmlGenericErrorContext,
        !           246:                "xmlMallocLoc : Out of free space\n");
        !           247:        xmlMemoryDump();
        !           248:        return(NULL);
        !           249:     }
        !           250:     p->mh_tag = MEMTAG;
        !           251:     p->mh_size = size;
        !           252:     p->mh_type = MALLOC_ATOMIC_TYPE;
        !           253:     p->mh_file = file;
        !           254:     p->mh_line = line;
        !           255:     xmlMutexLock(xmlMemMutex);
        !           256:     p->mh_number = ++block;
        !           257:     debugMemSize += size;
        !           258:     debugMemBlocks++;
        !           259:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
        !           260: #ifdef MEM_LIST
        !           261:     debugmem_list_add(p);
        !           262: #endif
        !           263:     xmlMutexUnlock(xmlMemMutex);
        !           264: 
        !           265: #ifdef DEBUG_MEMORY
        !           266:     xmlGenericError(xmlGenericErrorContext,
        !           267:            "Malloc(%d) Ok\n",size);
        !           268: #endif
        !           269: 
        !           270:     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
        !           271: 
        !           272:     ret = HDR_2_CLIENT(p);
        !           273: 
        !           274:     if (xmlMemTraceBlockAt == ret) {
        !           275:        xmlGenericError(xmlGenericErrorContext,
        !           276:                        "%p : Malloc(%ld) Ok\n", xmlMemTraceBlockAt, size);
        !           277:        xmlMallocBreakpoint();
        !           278:     }
        !           279: 
        !           280:     TEST_POINT
        !           281: 
        !           282:     return(ret);
        !           283: }
        !           284: /**
        !           285:  * xmlMemMalloc:
        !           286:  * @size:  an int specifying the size in byte to allocate.
        !           287:  *
        !           288:  * a malloc() equivalent, with logging of the allocation info.
        !           289:  *
        !           290:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
        !           291:  */
        !           292: 
        !           293: void *
        !           294: xmlMemMalloc(size_t size)
        !           295: {
        !           296:     return(xmlMallocLoc(size, "none", 0));
        !           297: }
        !           298: 
        !           299: /**
        !           300:  * xmlReallocLoc:
        !           301:  * @ptr:  the initial memory block pointer
        !           302:  * @size:  an int specifying the size in byte to allocate.
        !           303:  * @file:  the file name or NULL
        !           304:  * @line:  the line number
        !           305:  *
        !           306:  * a realloc() equivalent, with logging of the allocation info.
        !           307:  *
        !           308:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
        !           309:  */
        !           310: 
        !           311: void *
        !           312: xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
        !           313: {
        !           314:     MEMHDR *p;
        !           315:     unsigned long number;
        !           316: #ifdef DEBUG_MEMORY
        !           317:     size_t oldsize;
        !           318: #endif
        !           319: 
        !           320:     if (ptr == NULL)
        !           321:         return(xmlMallocLoc(size, file, line));
        !           322: 
        !           323:     if (!xmlMemInitialized) xmlInitMemory();
        !           324:     TEST_POINT
        !           325: 
        !           326:     p = CLIENT_2_HDR(ptr);
        !           327:     number = p->mh_number;
        !           328:     if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
        !           329:     if (p->mh_tag != MEMTAG) {
        !           330:        Mem_Tag_Err(p);
        !           331:         goto error;
        !           332:     }
        !           333:     p->mh_tag = ~MEMTAG;
        !           334:     xmlMutexLock(xmlMemMutex);
        !           335:     debugMemSize -= p->mh_size;
        !           336:     debugMemBlocks--;
        !           337: #ifdef DEBUG_MEMORY
        !           338:     oldsize = p->mh_size;
        !           339: #endif
        !           340: #ifdef MEM_LIST
        !           341:     debugmem_list_delete(p);
        !           342: #endif
        !           343:     xmlMutexUnlock(xmlMemMutex);
        !           344: 
        !           345:     p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
        !           346:     if (!p) {
        !           347:         goto error;
        !           348:     }
        !           349:     if (xmlMemTraceBlockAt == ptr) {
        !           350:        xmlGenericError(xmlGenericErrorContext,
        !           351:                        "%p : Realloced(%ld -> %ld) Ok\n",
        !           352:                        xmlMemTraceBlockAt, p->mh_size, size);
        !           353:        xmlMallocBreakpoint();
        !           354:     }
        !           355:     p->mh_tag = MEMTAG;
        !           356:     p->mh_number = number;
        !           357:     p->mh_type = REALLOC_TYPE;
        !           358:     p->mh_size = size;
        !           359:     p->mh_file = file;
        !           360:     p->mh_line = line;
        !           361:     xmlMutexLock(xmlMemMutex);
        !           362:     debugMemSize += size;
        !           363:     debugMemBlocks++;
        !           364:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
        !           365: #ifdef MEM_LIST
        !           366:     debugmem_list_add(p);
        !           367: #endif
        !           368:     xmlMutexUnlock(xmlMemMutex);
        !           369: 
        !           370:     TEST_POINT
        !           371: 
        !           372: #ifdef DEBUG_MEMORY
        !           373:     xmlGenericError(xmlGenericErrorContext,
        !           374:            "Realloced(%d to %d) Ok\n", oldsize, size);
        !           375: #endif
        !           376:     return(HDR_2_CLIENT(p));
        !           377: 
        !           378: error:
        !           379:     return(NULL);
        !           380: }
        !           381: 
        !           382: /**
        !           383:  * xmlMemRealloc:
        !           384:  * @ptr:  the initial memory block pointer
        !           385:  * @size:  an int specifying the size in byte to allocate.
        !           386:  *
        !           387:  * a realloc() equivalent, with logging of the allocation info.
        !           388:  *
        !           389:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
        !           390:  */
        !           391: 
        !           392: void *
        !           393: xmlMemRealloc(void *ptr,size_t size) {
        !           394:     return(xmlReallocLoc(ptr, size, "none", 0));
        !           395: }
        !           396: 
        !           397: /**
        !           398:  * xmlMemFree:
        !           399:  * @ptr:  the memory block pointer
        !           400:  *
        !           401:  * a free() equivalent, with error checking.
        !           402:  */
        !           403: void
        !           404: xmlMemFree(void *ptr)
        !           405: {
        !           406:     MEMHDR *p;
        !           407:     char *target;
        !           408: #ifdef DEBUG_MEMORY
        !           409:     size_t size;
        !           410: #endif
        !           411: 
        !           412:     if (ptr == NULL)
        !           413:        return;
        !           414: 
        !           415:     if (ptr == (void *) -1) {
        !           416:        xmlGenericError(xmlGenericErrorContext,
        !           417:            "trying to free pointer from freed area\n");
        !           418:         goto error;
        !           419:     }
        !           420: 
        !           421:     if (xmlMemTraceBlockAt == ptr) {
        !           422:        xmlGenericError(xmlGenericErrorContext,
        !           423:                        "%p : Freed()\n", xmlMemTraceBlockAt);
        !           424:        xmlMallocBreakpoint();
        !           425:     }
        !           426: 
        !           427:     TEST_POINT
        !           428: 
        !           429:     target = (char *) ptr;
        !           430: 
        !           431:     p = CLIENT_2_HDR(ptr);
        !           432:     if (p->mh_tag != MEMTAG) {
        !           433:         Mem_Tag_Err(p);
        !           434:         goto error;
        !           435:     }
        !           436:     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
        !           437:     p->mh_tag = ~MEMTAG;
        !           438:     memset(target, -1, p->mh_size);
        !           439:     xmlMutexLock(xmlMemMutex);
        !           440:     debugMemSize -= p->mh_size;
        !           441:     debugMemBlocks--;
        !           442: #ifdef DEBUG_MEMORY
        !           443:     size = p->mh_size;
        !           444: #endif
        !           445: #ifdef MEM_LIST
        !           446:     debugmem_list_delete(p);
        !           447: #endif
        !           448:     xmlMutexUnlock(xmlMemMutex);
        !           449: 
        !           450:     free(p);
        !           451: 
        !           452:     TEST_POINT
        !           453: 
        !           454: #ifdef DEBUG_MEMORY
        !           455:     xmlGenericError(xmlGenericErrorContext,
        !           456:            "Freed(%d) Ok\n", size);
        !           457: #endif
        !           458: 
        !           459:     return;
        !           460: 
        !           461: error:
        !           462:     xmlGenericError(xmlGenericErrorContext,
        !           463:            "xmlMemFree(%lX) error\n", (unsigned long) ptr);
        !           464:     xmlMallocBreakpoint();
        !           465:     return;
        !           466: }
        !           467: 
        !           468: /**
        !           469:  * xmlMemStrdupLoc:
        !           470:  * @str:  the initial string pointer
        !           471:  * @file:  the file name or NULL
        !           472:  * @line:  the line number
        !           473:  *
        !           474:  * a strdup() equivalent, with logging of the allocation info.
        !           475:  *
        !           476:  * Returns a pointer to the new string or NULL if allocation error occurred.
        !           477:  */
        !           478: 
        !           479: char *
        !           480: xmlMemStrdupLoc(const char *str, const char *file, int line)
        !           481: {
        !           482:     char *s;
        !           483:     size_t size = strlen(str) + 1;
        !           484:     MEMHDR *p;
        !           485: 
        !           486:     if (!xmlMemInitialized) xmlInitMemory();
        !           487:     TEST_POINT
        !           488: 
        !           489:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
        !           490:     if (!p) {
        !           491:       goto error;
        !           492:     }
        !           493:     p->mh_tag = MEMTAG;
        !           494:     p->mh_size = size;
        !           495:     p->mh_type = STRDUP_TYPE;
        !           496:     p->mh_file = file;
        !           497:     p->mh_line = line;
        !           498:     xmlMutexLock(xmlMemMutex);
        !           499:     p->mh_number = ++block;
        !           500:     debugMemSize += size;
        !           501:     debugMemBlocks++;
        !           502:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
        !           503: #ifdef MEM_LIST
        !           504:     debugmem_list_add(p);
        !           505: #endif
        !           506:     xmlMutexUnlock(xmlMemMutex);
        !           507: 
        !           508:     s = (char *) HDR_2_CLIENT(p);
        !           509: 
        !           510:     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
        !           511: 
        !           512:     if (s != NULL)
        !           513:       strcpy(s,str);
        !           514:     else
        !           515:       goto error;
        !           516: 
        !           517:     TEST_POINT
        !           518: 
        !           519:     if (xmlMemTraceBlockAt == s) {
        !           520:        xmlGenericError(xmlGenericErrorContext,
        !           521:                        "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
        !           522:        xmlMallocBreakpoint();
        !           523:     }
        !           524: 
        !           525:     return(s);
        !           526: 
        !           527: error:
        !           528:     return(NULL);
        !           529: }
        !           530: 
        !           531: /**
        !           532:  * xmlMemoryStrdup:
        !           533:  * @str:  the initial string pointer
        !           534:  *
        !           535:  * a strdup() equivalent, with logging of the allocation info.
        !           536:  *
        !           537:  * Returns a pointer to the new string or NULL if allocation error occurred.
        !           538:  */
        !           539: 
        !           540: char *
        !           541: xmlMemoryStrdup(const char *str) {
        !           542:     return(xmlMemStrdupLoc(str, "none", 0));
        !           543: }
        !           544: 
        !           545: /**
        !           546:  * xmlMemUsed:
        !           547:  *
        !           548:  * Provides the amount of memory currently allocated
        !           549:  *
        !           550:  * Returns an int representing the amount of memory allocated.
        !           551:  */
        !           552: 
        !           553: int
        !           554: xmlMemUsed(void) {
        !           555:      return(debugMemSize);
        !           556: }
        !           557: 
        !           558: /**
        !           559:  * xmlMemBlocks:
        !           560:  *
        !           561:  * Provides the number of memory areas currently allocated
        !           562:  *
        !           563:  * Returns an int representing the number of blocks
        !           564:  */
        !           565: 
        !           566: int
        !           567: xmlMemBlocks(void) {
        !           568:      return(debugMemBlocks);
        !           569: }
        !           570: 
        !           571: #ifdef MEM_LIST
        !           572: /**
        !           573:  * xmlMemContentShow:
        !           574:  * @fp:  a FILE descriptor used as the output file
        !           575:  * @p:  a memory block header
        !           576:  *
        !           577:  * tries to show some content from the memory block
        !           578:  */
        !           579: 
        !           580: static void
        !           581: xmlMemContentShow(FILE *fp, MEMHDR *p)
        !           582: {
        !           583:     int i,j,k,len = p->mh_size;
        !           584:     const char *buf = (const char *) HDR_2_CLIENT(p);
        !           585: 
        !           586:     if (p == NULL) {
        !           587:        fprintf(fp, " NULL");
        !           588:        return;
        !           589:     }
        !           590: 
        !           591:     for (i = 0;i < len;i++) {
        !           592:         if (buf[i] == 0) break;
        !           593:        if (!isprint((unsigned char) buf[i])) break;
        !           594:     }
        !           595:     if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
        !           596:         if (len >= 4) {
        !           597:            MEMHDR *q;
        !           598:            void *cur;
        !           599: 
        !           600:             for (j = 0;(j < len -3) && (j < 40);j += 4) {
        !           601:                cur = *((void **) &buf[j]);
        !           602:                q = CLIENT_2_HDR(cur);
        !           603:                p = memlist;
        !           604:                k = 0;
        !           605:                while (p != NULL) {
        !           606:                    if (p == q) break;
        !           607:                    p = p->mh_next;
        !           608:                    if (k++ > 100) break;
        !           609:                }
        !           610:                if ((p != NULL) && (p == q)) {
        !           611:                    fprintf(fp, " pointer to #%lu at index %d",
        !           612:                            p->mh_number, j);
        !           613:                    return;
        !           614:                }
        !           615:            }
        !           616:        }
        !           617:     } else if ((i == 0) && (buf[i] == 0)) {
        !           618:         fprintf(fp," null");
        !           619:     } else {
        !           620:         if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
        !           621:        else {
        !           622:             fprintf(fp," [");
        !           623:            for (j = 0;j < i;j++)
        !           624:                 fprintf(fp,"%c", buf[j]);
        !           625:             fprintf(fp,"]");
        !           626:        }
        !           627:     }
        !           628: }
        !           629: #endif
        !           630: 
        !           631: /**
        !           632:  * xmlMemDisplayLast:
        !           633:  * @fp:  a FILE descriptor used as the output file, if NULL, the result is
        !           634:  *       written to the file .memorylist
        !           635:  * @nbBytes: the amount of memory to dump
        !           636:  *
        !           637:  * the last nbBytes of memory allocated and not freed, useful for dumping
        !           638:  * the memory left allocated between two places at runtime.
        !           639:  */
        !           640: 
        !           641: void
        !           642: xmlMemDisplayLast(FILE *fp, long nbBytes)
        !           643: {
        !           644: #ifdef MEM_LIST
        !           645:     MEMHDR *p;
        !           646:     unsigned idx;
        !           647:     int     nb = 0;
        !           648: #endif
        !           649:     FILE *old_fp = fp;
        !           650: 
        !           651:     if (nbBytes <= 0)
        !           652:         return;
        !           653: 
        !           654:     if (fp == NULL) {
        !           655:        fp = fopen(".memorylist", "w");
        !           656:        if (fp == NULL)
        !           657:            return;
        !           658:     }
        !           659: 
        !           660: #ifdef MEM_LIST
        !           661:     fprintf(fp,"   Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
        !           662:             nbBytes, debugMemSize, debugMaxMemSize);
        !           663:     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
        !           664:     idx = 0;
        !           665:     xmlMutexLock(xmlMemMutex);
        !           666:     p = memlist;
        !           667:     while ((p) && (nbBytes > 0)) {
        !           668:          fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
        !           669:                  (unsigned long)p->mh_size);
        !           670:         switch (p->mh_type) {
        !           671:            case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
        !           672:            case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
        !           673:            case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
        !           674:            case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
        !           675:            case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
        !           676:            default:
        !           677:                fprintf(fp,"Unknown memory block, may be corrupted");
        !           678:                xmlMutexUnlock(xmlMemMutex);
        !           679:                if (old_fp == NULL)
        !           680:                    fclose(fp);
        !           681:                return;
        !           682:         }
        !           683:        if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
        !           684:         if (p->mh_tag != MEMTAG)
        !           685:              fprintf(fp,"  INVALID");
        !           686:         nb++;
        !           687:        if (nb < 100)
        !           688:            xmlMemContentShow(fp, p);
        !           689:        else
        !           690:            fprintf(fp," skip");
        !           691: 
        !           692:         fprintf(fp,"\n");
        !           693:        nbBytes -= (unsigned long)p->mh_size;
        !           694:         p = p->mh_next;
        !           695:     }
        !           696:     xmlMutexUnlock(xmlMemMutex);
        !           697: #else
        !           698:     fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
        !           699: #endif
        !           700:     if (old_fp == NULL)
        !           701:        fclose(fp);
        !           702: }
        !           703: 
        !           704: /**
        !           705:  * xmlMemDisplay:
        !           706:  * @fp:  a FILE descriptor used as the output file, if NULL, the result is
        !           707:  *       written to the file .memorylist
        !           708:  *
        !           709:  * show in-extenso the memory blocks allocated
        !           710:  */
        !           711: 
        !           712: void
        !           713: xmlMemDisplay(FILE *fp)
        !           714: {
        !           715: #ifdef MEM_LIST
        !           716:     MEMHDR *p;
        !           717:     unsigned idx;
        !           718:     int     nb = 0;
        !           719: #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
        !           720:     time_t currentTime;
        !           721:     char buf[500];
        !           722:     struct tm * tstruct;
        !           723: #endif
        !           724: #endif
        !           725:     FILE *old_fp = fp;
        !           726: 
        !           727:     if (fp == NULL) {
        !           728:        fp = fopen(".memorylist", "w");
        !           729:        if (fp == NULL)
        !           730:            return;
        !           731:     }
        !           732: 
        !           733: #ifdef MEM_LIST
        !           734: #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
        !           735:     currentTime = time(NULL);
        !           736:     tstruct = localtime(&currentTime);
        !           737:     strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
        !           738:     fprintf(fp,"      %s\n\n", buf);
        !           739: #endif
        !           740: 
        !           741: 
        !           742:     fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
        !           743:             debugMemSize, debugMaxMemSize);
        !           744:     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
        !           745:     idx = 0;
        !           746:     xmlMutexLock(xmlMemMutex);
        !           747:     p = memlist;
        !           748:     while (p) {
        !           749:          fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
        !           750:                  (unsigned long)p->mh_size);
        !           751:         switch (p->mh_type) {
        !           752:            case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
        !           753:            case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
        !           754:            case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
        !           755:            case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
        !           756:            case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
        !           757:            default:
        !           758:                fprintf(fp,"Unknown memory block, may be corrupted");
        !           759:                xmlMutexUnlock(xmlMemMutex);
        !           760:                if (old_fp == NULL)
        !           761:                    fclose(fp);
        !           762:                return;
        !           763:         }
        !           764:        if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
        !           765:         if (p->mh_tag != MEMTAG)
        !           766:              fprintf(fp,"  INVALID");
        !           767:         nb++;
        !           768:        if (nb < 100)
        !           769:            xmlMemContentShow(fp, p);
        !           770:        else
        !           771:            fprintf(fp," skip");
        !           772: 
        !           773:         fprintf(fp,"\n");
        !           774:         p = p->mh_next;
        !           775:     }
        !           776:     xmlMutexUnlock(xmlMemMutex);
        !           777: #else
        !           778:     fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
        !           779: #endif
        !           780:     if (old_fp == NULL)
        !           781:        fclose(fp);
        !           782: }
        !           783: 
        !           784: #ifdef MEM_LIST
        !           785: 
        !           786: static void debugmem_list_add(MEMHDR *p)
        !           787: {
        !           788:      p->mh_next = memlist;
        !           789:      p->mh_prev = NULL;
        !           790:      if (memlist) memlist->mh_prev = p;
        !           791:      memlist = p;
        !           792: #ifdef MEM_LIST_DEBUG
        !           793:      if (stderr)
        !           794:      Mem_Display(stderr);
        !           795: #endif
        !           796: }
        !           797: 
        !           798: static void debugmem_list_delete(MEMHDR *p)
        !           799: {
        !           800:      if (p->mh_next)
        !           801:      p->mh_next->mh_prev = p->mh_prev;
        !           802:      if (p->mh_prev)
        !           803:      p->mh_prev->mh_next = p->mh_next;
        !           804:      else memlist = p->mh_next;
        !           805: #ifdef MEM_LIST_DEBUG
        !           806:      if (stderr)
        !           807:      Mem_Display(stderr);
        !           808: #endif
        !           809: }
        !           810: 
        !           811: #endif
        !           812: 
        !           813: /*
        !           814:  * debugmem_tag_error:
        !           815:  *
        !           816:  * internal error function.
        !           817:  */
        !           818: 
        !           819: static void debugmem_tag_error(void *p)
        !           820: {
        !           821:      xmlGenericError(xmlGenericErrorContext,
        !           822:             "Memory tag error occurs :%p \n\t bye\n", p);
        !           823: #ifdef MEM_LIST
        !           824:      if (stderr)
        !           825:      xmlMemDisplay(stderr);
        !           826: #endif
        !           827: }
        !           828: 
        !           829: #ifdef MEM_LIST
        !           830: static FILE *xmlMemoryDumpFile = NULL;
        !           831: #endif
        !           832: 
        !           833: /**
        !           834:  * xmlMemShow:
        !           835:  * @fp:  a FILE descriptor used as the output file
        !           836:  * @nr:  number of entries to dump
        !           837:  *
        !           838:  * show a show display of the memory allocated, and dump
        !           839:  * the @nr last allocated areas which were not freed
        !           840:  */
        !           841: 
        !           842: void
        !           843: xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
        !           844: {
        !           845: #ifdef MEM_LIST
        !           846:     MEMHDR *p;
        !           847: #endif
        !           848: 
        !           849:     if (fp != NULL)
        !           850:        fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
        !           851:                debugMemSize, debugMaxMemSize);
        !           852: #ifdef MEM_LIST
        !           853:     xmlMutexLock(xmlMemMutex);
        !           854:     if (nr > 0) {
        !           855:        fprintf(fp,"NUMBER   SIZE  TYPE   WHERE\n");
        !           856:        p = memlist;
        !           857:        while ((p) && nr > 0) {
        !           858:              fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
        !           859:            switch (p->mh_type) {
        !           860:               case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
        !           861:               case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
        !           862:               case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
        !           863:              case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
        !           864:              case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
        !           865:                default:fprintf(fp,"   ???    in ");break;
        !           866:            }
        !           867:            if (p->mh_file != NULL)
        !           868:                fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
        !           869:            if (p->mh_tag != MEMTAG)
        !           870:                fprintf(fp,"  INVALID");
        !           871:            xmlMemContentShow(fp, p);
        !           872:            fprintf(fp,"\n");
        !           873:            nr--;
        !           874:            p = p->mh_next;
        !           875:        }
        !           876:     }
        !           877:     xmlMutexUnlock(xmlMemMutex);
        !           878: #endif /* MEM_LIST */
        !           879: }
        !           880: 
        !           881: /**
        !           882:  * xmlMemoryDump:
        !           883:  *
        !           884:  * Dump in-extenso the memory blocks allocated to the file .memorylist
        !           885:  */
        !           886: 
        !           887: void
        !           888: xmlMemoryDump(void)
        !           889: {
        !           890: #ifdef MEM_LIST
        !           891:     FILE *dump;
        !           892: 
        !           893:     if (debugMaxMemSize == 0)
        !           894:        return;
        !           895:     dump = fopen(".memdump", "w");
        !           896:     if (dump == NULL)
        !           897:        xmlMemoryDumpFile = stderr;
        !           898:     else xmlMemoryDumpFile = dump;
        !           899: 
        !           900:     xmlMemDisplay(xmlMemoryDumpFile);
        !           901: 
        !           902:     if (dump != NULL) fclose(dump);
        !           903: #endif /* MEM_LIST */
        !           904: }
        !           905: 
        !           906: 
        !           907: /****************************************************************
        !           908:  *                                                             *
        !           909:  *             Initialization Routines                         *
        !           910:  *                                                             *
        !           911:  ****************************************************************/
        !           912: 
        !           913: /**
        !           914:  * xmlInitMemory:
        !           915:  *
        !           916:  * Initialize the memory layer.
        !           917:  *
        !           918:  * Returns 0 on success
        !           919:  */
        !           920: int
        !           921: xmlInitMemory(void)
        !           922: {
        !           923: #ifdef HAVE_STDLIB_H
        !           924:      char *breakpoint;
        !           925: #endif
        !           926: #ifdef DEBUG_MEMORY
        !           927:      xmlGenericError(xmlGenericErrorContext,
        !           928:             "xmlInitMemory()\n");
        !           929: #endif
        !           930:     /*
        !           931:      This is really not good code (see Bug 130419).  Suggestions for
        !           932:      improvement will be welcome!
        !           933:     */
        !           934:      if (xmlMemInitialized) return(-1);
        !           935:      xmlMemInitialized = 1;
        !           936:      xmlMemMutex = xmlNewMutex();
        !           937: 
        !           938: #ifdef HAVE_STDLIB_H
        !           939:      breakpoint = getenv("XML_MEM_BREAKPOINT");
        !           940:      if (breakpoint != NULL) {
        !           941:          sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
        !           942:      }
        !           943: #endif
        !           944: #ifdef HAVE_STDLIB_H
        !           945:      breakpoint = getenv("XML_MEM_TRACE");
        !           946:      if (breakpoint != NULL) {
        !           947:          sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
        !           948:      }
        !           949: #endif
        !           950: 
        !           951: #ifdef DEBUG_MEMORY
        !           952:      xmlGenericError(xmlGenericErrorContext,
        !           953:             "xmlInitMemory() Ok\n");
        !           954: #endif
        !           955:      return(0);
        !           956: }
        !           957: 
        !           958: /**
        !           959:  * xmlCleanupMemory:
        !           960:  *
        !           961:  * Free up all the memory allocated by the library for its own
        !           962:  * use. This should not be called by user level code.
        !           963:  */
        !           964: void
        !           965: xmlCleanupMemory(void) {
        !           966: #ifdef DEBUG_MEMORY
        !           967:      xmlGenericError(xmlGenericErrorContext,
        !           968:             "xmlCleanupMemory()\n");
        !           969: #endif
        !           970:     if (xmlMemInitialized == 0)
        !           971:         return;
        !           972: 
        !           973:     xmlFreeMutex(xmlMemMutex);
        !           974:     xmlMemMutex = NULL;
        !           975:     xmlMemInitialized = 0;
        !           976: #ifdef DEBUG_MEMORY
        !           977:      xmlGenericError(xmlGenericErrorContext,
        !           978:             "xmlCleanupMemory() Ok\n");
        !           979: #endif
        !           980: }
        !           981: 
        !           982: /**
        !           983:  * xmlMemSetup:
        !           984:  * @freeFunc: the free() function to use
        !           985:  * @mallocFunc: the malloc() function to use
        !           986:  * @reallocFunc: the realloc() function to use
        !           987:  * @strdupFunc: the strdup() function to use
        !           988:  *
        !           989:  * Override the default memory access functions with a new set
        !           990:  * This has to be called before any other libxml routines !
        !           991:  *
        !           992:  * Should this be blocked if there was already some allocations
        !           993:  * done ?
        !           994:  *
        !           995:  * Returns 0 on success
        !           996:  */
        !           997: int
        !           998: xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
        !           999:             xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
        !          1000: #ifdef DEBUG_MEMORY
        !          1001:      xmlGenericError(xmlGenericErrorContext,
        !          1002:             "xmlMemSetup()\n");
        !          1003: #endif
        !          1004:     if (freeFunc == NULL)
        !          1005:        return(-1);
        !          1006:     if (mallocFunc == NULL)
        !          1007:        return(-1);
        !          1008:     if (reallocFunc == NULL)
        !          1009:        return(-1);
        !          1010:     if (strdupFunc == NULL)
        !          1011:        return(-1);
        !          1012:     xmlFree = freeFunc;
        !          1013:     xmlMalloc = mallocFunc;
        !          1014:     xmlMallocAtomic = mallocFunc;
        !          1015:     xmlRealloc = reallocFunc;
        !          1016:     xmlMemStrdup = strdupFunc;
        !          1017: #ifdef DEBUG_MEMORY
        !          1018:      xmlGenericError(xmlGenericErrorContext,
        !          1019:             "xmlMemSetup() Ok\n");
        !          1020: #endif
        !          1021:     return(0);
        !          1022: }
        !          1023: 
        !          1024: /**
        !          1025:  * xmlMemGet:
        !          1026:  * @freeFunc: place to save the free() function in use
        !          1027:  * @mallocFunc: place to save the malloc() function in use
        !          1028:  * @reallocFunc: place to save the realloc() function in use
        !          1029:  * @strdupFunc: place to save the strdup() function in use
        !          1030:  *
        !          1031:  * Provides the memory access functions set currently in use
        !          1032:  *
        !          1033:  * Returns 0 on success
        !          1034:  */
        !          1035: int
        !          1036: xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
        !          1037:          xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
        !          1038:     if (freeFunc != NULL) *freeFunc = xmlFree;
        !          1039:     if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
        !          1040:     if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
        !          1041:     if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
        !          1042:     return(0);
        !          1043: }
        !          1044: 
        !          1045: /**
        !          1046:  * xmlGcMemSetup:
        !          1047:  * @freeFunc: the free() function to use
        !          1048:  * @mallocFunc: the malloc() function to use
        !          1049:  * @mallocAtomicFunc: the malloc() function to use for atomic allocations
        !          1050:  * @reallocFunc: the realloc() function to use
        !          1051:  * @strdupFunc: the strdup() function to use
        !          1052:  *
        !          1053:  * Override the default memory access functions with a new set
        !          1054:  * This has to be called before any other libxml routines !
        !          1055:  * The mallocAtomicFunc is specialized for atomic block
        !          1056:  * allocations (i.e. of areas  useful for garbage collected memory allocators
        !          1057:  *
        !          1058:  * Should this be blocked if there was already some allocations
        !          1059:  * done ?
        !          1060:  *
        !          1061:  * Returns 0 on success
        !          1062:  */
        !          1063: int
        !          1064: xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
        !          1065:               xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
        !          1066:              xmlStrdupFunc strdupFunc) {
        !          1067: #ifdef DEBUG_MEMORY
        !          1068:      xmlGenericError(xmlGenericErrorContext,
        !          1069:             "xmlGcMemSetup()\n");
        !          1070: #endif
        !          1071:     if (freeFunc == NULL)
        !          1072:        return(-1);
        !          1073:     if (mallocFunc == NULL)
        !          1074:        return(-1);
        !          1075:     if (mallocAtomicFunc == NULL)
        !          1076:        return(-1);
        !          1077:     if (reallocFunc == NULL)
        !          1078:        return(-1);
        !          1079:     if (strdupFunc == NULL)
        !          1080:        return(-1);
        !          1081:     xmlFree = freeFunc;
        !          1082:     xmlMalloc = mallocFunc;
        !          1083:     xmlMallocAtomic = mallocAtomicFunc;
        !          1084:     xmlRealloc = reallocFunc;
        !          1085:     xmlMemStrdup = strdupFunc;
        !          1086: #ifdef DEBUG_MEMORY
        !          1087:      xmlGenericError(xmlGenericErrorContext,
        !          1088:             "xmlGcMemSetup() Ok\n");
        !          1089: #endif
        !          1090:     return(0);
        !          1091: }
        !          1092: 
        !          1093: /**
        !          1094:  * xmlGcMemGet:
        !          1095:  * @freeFunc: place to save the free() function in use
        !          1096:  * @mallocFunc: place to save the malloc() function in use
        !          1097:  * @mallocAtomicFunc: place to save the atomic malloc() function in use
        !          1098:  * @reallocFunc: place to save the realloc() function in use
        !          1099:  * @strdupFunc: place to save the strdup() function in use
        !          1100:  *
        !          1101:  * Provides the memory access functions set currently in use
        !          1102:  * The mallocAtomicFunc is specialized for atomic block
        !          1103:  * allocations (i.e. of areas  useful for garbage collected memory allocators
        !          1104:  *
        !          1105:  * Returns 0 on success
        !          1106:  */
        !          1107: int
        !          1108: xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
        !          1109:             xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
        !          1110:            xmlStrdupFunc *strdupFunc) {
        !          1111:     if (freeFunc != NULL) *freeFunc = xmlFree;
        !          1112:     if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
        !          1113:     if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
        !          1114:     if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
        !          1115:     if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
        !          1116:     return(0);
        !          1117: }
        !          1118: 
        !          1119: #define bottom_xmlmemory
        !          1120: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>