Annotation of embedaddon/libxml2/xmlmemory.c, revision 1.1.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>