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

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

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