xmlmemory.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:15k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * memory.c:  libxml memory allocator wrapper.
  3.  *
  4.  * Daniel.Veillard@w3.org
  5.  */
  6. #ifdef WIN32
  7. #include "win32config.h"
  8. #else
  9. #include "config.h"
  10. #endif
  11. #include <stdio.h>
  12. #include <string.h>
  13. #ifdef HAVE_SYS_TYPES_H
  14. #include <sys/types.h>
  15. #endif
  16. #ifdef HAVE_TIME_H
  17. #include <time.h>
  18. #endif
  19. #ifdef HAVE_MALLOC_H
  20. #include <malloc.h>
  21. #endif
  22. #ifdef HAVE_STDLIB_H
  23. #include <stdlib.h>
  24. #endif
  25. #ifdef HAVE_CTYPE_H
  26. #include <ctype.h>
  27. #endif
  28. #include <libxml/xmlmemory.h>
  29. #ifdef xmlMalloc
  30. #undef xmlMalloc
  31. #endif
  32. #ifdef xmlRealloc
  33. #undef xmlRealloc
  34. #endif
  35. #ifdef xmlMemStrdup
  36. #undef xmlMemStrdup
  37. #endif
  38. /*
  39.  * Each of the blocks allocated begin with a header containing informations
  40.  */
  41. #define MEMTAG 0x5aa5
  42. #define MALLOC_TYPE 1
  43. #define REALLOC_TYPE 2
  44. #define STRDUP_TYPE 3
  45. typedef struct memnod {
  46.     unsigned int   mh_tag;
  47.     unsigned int   mh_type;
  48.     unsigned long  mh_number;
  49.     size_t         mh_size;
  50. #ifdef MEM_LIST
  51.    struct memnod *mh_next;
  52.    struct memnod *mh_prev;
  53. #endif
  54.    const char    *mh_file;
  55.    unsigned int   mh_line;
  56. }  MEMHDR;
  57. #ifdef SUN4
  58. #define ALIGN_SIZE  16
  59. #else
  60. #define ALIGN_SIZE  sizeof(double)
  61. #endif
  62. #define HDR_SIZE    sizeof(MEMHDR)
  63. #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) 
  64.       / ALIGN_SIZE ) * ALIGN_SIZE)
  65. #define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
  66. #define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
  67. static unsigned long  debugMemSize = 0;
  68. static unsigned long  debugMaxMemSize = 0;
  69. static int block=0;
  70. int xmlMemStopAtBlock = 0;
  71. int xmlMemInitialized = 0;
  72. #ifdef MEM_LIST
  73. static MEMHDR *memlist = NULL;
  74. #endif
  75. void debugmem_tag_error(void *addr);
  76. #ifdef MEM_LIST
  77. void  debugmem_list_add(MEMHDR *);
  78. void debugmem_list_delete(MEMHDR *);
  79. #endif
  80. #define Mem_Tag_Err(a) debugmem_tag_error(a);
  81. #ifndef TEST_POINT
  82. #define TEST_POINT
  83. #endif
  84. /**
  85.  * xmlMallocBreakpoint:
  86.  *
  87.  * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
  88.  * number reaches the specified value this function is called. One need to add a breakpoint
  89.  * to it to get the context in which the given block is allocated.
  90.  */
  91. void
  92. xmlMallocBreakpoint(void) {
  93.     fprintf(stderr, "xmlMallocBreakpoint reached on block %dn", xmlMemStopAtBlock);
  94. }
  95. /**
  96.  * xmlMallocLoc:
  97.  * @size:  an int specifying the size in byte to allocate.
  98.  * @file:  the file name or NULL
  99.   @file:  the line number
  100.  *
  101.  * a malloc() equivalent, with logging of the allocation info.
  102.  *
  103.  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  104.  */
  105. void *
  106. xmlMallocLoc(int size, const char * file, int line)
  107. {
  108.     MEMHDR *p;
  109.     
  110.     if (!xmlMemInitialized) xmlInitMemory();
  111. #ifdef DEBUG_MEMORY
  112.     fprintf(stderr, "Malloc(%d)n",size);
  113. #endif
  114.     TEST_POINT
  115.     
  116.     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
  117.     if (!p) {
  118. fprintf(stderr, "xmlMalloc : Out of free spacen");
  119. xmlMemoryDump();
  120. return(NULL);
  121.     }   
  122.     p->mh_tag = MEMTAG;
  123.     p->mh_number = ++block;
  124.     p->mh_size = size;
  125.     p->mh_type = MALLOC_TYPE;
  126.     p->mh_file = file;
  127.     p->mh_line = line;
  128.     debugMemSize += size;
  129.     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
  130. #ifdef MEM_LIST
  131.     debugmem_list_add(p);
  132. #endif
  133. #ifdef DEBUG_MEMORY
  134.     fprintf(stderr, "Malloc(%d) Okn",size);
  135. #endif
  136.     
  137.     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
  138.     TEST_POINT
  139.     return(HDR_2_CLIENT(p));
  140. }
  141. /**
  142.  * xmlMemMalloc:
  143.  * @size:  an int specifying the size in byte to allocate.
  144.  *
  145.  * a malloc() equivalent, with logging of the allocation info.
  146.  *
  147.  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  148.  */
  149. void *
  150. xmlMemMalloc(int size)
  151. {
  152.     return(xmlMallocLoc(size, "none", 0));
  153. }
  154. /**
  155.  * xmlReallocLoc:
  156.  * @ptr:  the initial memory block pointer
  157.  * @size:  an int specifying the size in byte to allocate.
  158.  * @file:  the file name or NULL
  159.  * @file:  the line number
  160.  *
  161.  * a realloc() equivalent, with logging of the allocation info.
  162.  *
  163.  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  164.  */
  165. void *
  166. xmlReallocLoc(void *ptr,int size, const char * file, int line)
  167. {
  168.     MEMHDR *p;
  169.     unsigned long number;
  170.     if (!xmlMemInitialized) xmlInitMemory();
  171.     TEST_POINT
  172.     p = CLIENT_2_HDR(ptr);
  173.     number = p->mh_number;
  174.     if (p->mh_tag != MEMTAG) {
  175.        Mem_Tag_Err(p);
  176.  goto error;
  177.     }
  178.     p->mh_tag = ~MEMTAG;
  179.     debugMemSize -= p->mh_size;
  180. #ifdef MEM_LIST
  181.     debugmem_list_delete(p);
  182. #endif
  183.     p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
  184.     if (!p) {
  185.  goto error;
  186.     }
  187.     p->mh_tag = MEMTAG;
  188.     p->mh_number = number;
  189.     p->mh_type = REALLOC_TYPE;
  190.     p->mh_size = size;
  191.     p->mh_file = file;
  192.     p->mh_line = line;
  193.     debugMemSize += size;
  194.     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
  195. #ifdef MEM_LIST
  196.     debugmem_list_add(p);
  197. #endif
  198.     TEST_POINT
  199.     return(HDR_2_CLIENT(p));
  200.     
  201. error:    
  202.     return(NULL);
  203. }
  204. /**
  205.  * xmlMemRealloc:
  206.  * @ptr:  the initial memory block pointer
  207.  * @size:  an int specifying the size in byte to allocate.
  208.  *
  209.  * a realloc() equivalent, with logging of the allocation info.
  210.  *
  211.  * Returns a pointer to the allocated area or NULL in case of lack of memory.
  212.  */
  213. void *
  214. xmlMemRealloc(void *ptr,int size) {
  215.     return(xmlReallocLoc(ptr, size, "none", 0));
  216. }
  217. /**
  218.  * xmlMemFree:
  219.  * @ptr:  the memory block pointer
  220.  *
  221.  * a free() equivalent, with error checking.
  222.  */
  223. void
  224. xmlMemFree(void *ptr)
  225. {
  226.     MEMHDR *p;
  227.     TEST_POINT
  228.     p = CLIENT_2_HDR(ptr);
  229.     if (p->mh_tag != MEMTAG) {
  230.        Mem_Tag_Err(p);
  231.        goto error;
  232.     }
  233.     p->mh_tag = ~MEMTAG;
  234.     debugMemSize -= p->mh_size;
  235. #ifdef MEM_LIST
  236.     debugmem_list_delete(p);
  237. #endif
  238.     free(p);
  239.     TEST_POINT
  240.     return;
  241.     
  242. error:    
  243.     fprintf(stderr, "xmlFree(%X) errorn", (unsigned int) ptr);
  244.     return;
  245. }
  246. /**
  247.  * xmlMemStrdupLoc:
  248.  * @ptr:  the initial string pointer
  249.  * @file:  the file name or NULL
  250.  * @file:  the line number
  251.  *
  252.  * a strdup() equivalent, with logging of the allocation info.
  253.  *
  254.  * Returns a pointer to the new string or NULL if allocation error occured.
  255.  */
  256. char *
  257. xmlMemStrdupLoc(const char *str, const char *file, int line)
  258. {
  259.     char *s;
  260.     size_t size = strlen(str) + 1;
  261.     MEMHDR *p;
  262.     if (!xmlMemInitialized) xmlInitMemory();
  263.     TEST_POINT
  264.     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
  265.     if (!p) {
  266.       goto error;
  267.     }
  268.     p->mh_tag = MEMTAG;
  269.     p->mh_number = ++block;
  270.     p->mh_size = size;
  271.     p->mh_type = STRDUP_TYPE;
  272.     p->mh_file = file;
  273.     p->mh_line = line;
  274.     debugMemSize += size;
  275.     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
  276. #ifdef MEM_LIST
  277.     debugmem_list_add(p);
  278. #endif
  279.     s = HDR_2_CLIENT(p);
  280.     
  281.     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
  282.     if (s != NULL)
  283.       strcpy(s,str);
  284.     else
  285.       goto error;
  286.     
  287.     TEST_POINT
  288.     return(s);
  289. error:
  290.     return(NULL);
  291. }
  292. /**
  293.  * xmlMemoryStrdup:
  294.  * @ptr:  the initial string pointer
  295.  *
  296.  * a strdup() equivalent, with logging of the allocation info.
  297.  *
  298.  * Returns a pointer to the new string or NULL if allocation error occured.
  299.  */
  300. char *
  301. xmlMemoryStrdup(const char *str) {
  302.     return(xmlMemStrdupLoc(str, "none", 0));
  303. }
  304. /**
  305.  * xmlMemUsed:
  306.  *
  307.  * returns the amount of memory currenly allocated
  308.  *
  309.  * Returns an int representing the amount of memory allocated.
  310.  */
  311. int
  312. xmlMemUsed(void) {
  313.      return(debugMemSize);
  314. }
  315. #ifdef MEM_LIST
  316. /**
  317.  * xmlMemContentShow:
  318.  * @fp:  a FILE descriptor used as the output file
  319.  * @p:  a memory block header
  320.  *
  321.  * tries to show some content from the memory block
  322.  */
  323. void
  324. xmlMemContentShow(FILE *fp, MEMHDR *p)
  325. {
  326.     int i,j,len = p->mh_size;
  327.     const char *buf = HDR_2_CLIENT(p);
  328.     for (i = 0;i < len;i++) {
  329.         if (buf[i] == 0) break;
  330. if (!isprint(buf[i])) break;
  331.     }
  332.     if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
  333.         if (len >= 4) {
  334.     MEMHDR *q;
  335.     void *cur;
  336.             for (j = 0;j < len -3;j += 4) {
  337. cur = *((void **) &buf[j]);
  338. q = CLIENT_2_HDR(cur);
  339. p = memlist;
  340. while (p != NULL) {
  341.     if (p == q) break;
  342.     p = p->mh_next;
  343. }
  344. if (p == q) {
  345.     fprintf(fp, " pointer to #%lu at index %d",
  346.             p->mh_number, j);
  347.     return;
  348. }
  349.     }
  350. }
  351.     } else if ((i == 0) && (buf[i] == 0)) {
  352.         fprintf(fp," null");
  353.     } else {
  354.         if (buf[i] == 0) fprintf(fp," "%.25s"", buf); 
  355. else {
  356.             fprintf(fp," [");
  357.     for (j = 0;j < i;j++)
  358.                 fprintf(fp,"%c", buf[j]);
  359.             fprintf(fp,"]");
  360. }
  361.     }
  362. }
  363. #endif
  364. /**
  365.  * xmlMemShow:
  366.  * @fp:  a FILE descriptor used as the output file
  367.  * @nr:  number of entries to dump
  368.  *
  369.  * show a show display of the memory allocated, and dump
  370.  * the @nr last allocated areas which were not freed
  371.  */
  372. void
  373. xmlMemShow(FILE *fp, int nr)
  374. {
  375. #ifdef MEM_LIST
  376.     MEMHDR *p;
  377. #endif
  378.     if (fp != NULL)
  379. fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lun",
  380. debugMemSize, debugMaxMemSize);
  381. #ifdef MEM_LIST
  382.     if (nr > 0) {
  383. fprintf(fp,"NUMBER   SIZE  TYPE   WHEREn");
  384. p = memlist;
  385. while ((p) && nr > 0) {
  386.       fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
  387.     switch (p->mh_type) {
  388.        case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
  389.        case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
  390.       case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
  391. default:fprintf(fp,"   ???    in ");break;
  392.     }
  393.     if (p->mh_file != NULL)
  394.         fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
  395.     if (p->mh_tag != MEMTAG)
  396. fprintf(fp,"  INVALID");
  397.     xmlMemContentShow(fp, p);
  398.     fprintf(fp,"n");
  399.     nr--;
  400.     p = p->mh_next;
  401. }
  402.     }
  403. #endif /* MEM_LIST */    
  404. }
  405. /**
  406.  * xmlMemDisplay:
  407.  * @fp:  a FILE descriptor used as the output file, if NULL, the result is
  408.  *       written to the file .memorylist
  409.  *
  410.  * show in-extenso the memory blocks allocated
  411.  */
  412. void
  413. xmlMemDisplay(FILE *fp)
  414. {
  415. #ifdef MEM_LIST
  416.     MEMHDR *p;
  417.     int     idx;
  418. #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
  419.     time_t currentTime;
  420.     char buf[500];
  421.     struct tm * tstruct;
  422.     currentTime = time(NULL);
  423.     tstruct = localtime(&currentTime);
  424.     strftime(buf, sizeof(buf) - 1, "%c", tstruct);
  425.     fprintf(fp,"      %snn", buf);
  426. #endif
  427.     
  428.     fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lun",
  429.             debugMemSize, debugMaxMemSize);
  430.     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPEn");
  431.     idx = 0;
  432.     p = memlist;
  433.     while (p) {
  434.   fprintf(fp,"%-5u  %6lu %6u ",idx++,p->mh_number,p->mh_size);
  435.         switch (p->mh_type) {
  436.            case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
  437.            case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
  438.           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
  439.                     default:fprintf(fp,"   ???    in ");break;
  440.         }
  441.   if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
  442.         if (p->mh_tag != MEMTAG)
  443.       fprintf(fp,"  INVALID");
  444. xmlMemContentShow(fp, p);
  445.         fprintf(fp,"n");
  446.         p = p->mh_next;
  447.     }
  448. #else
  449.     fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)n");
  450. #endif
  451. }
  452. #ifdef MEM_LIST
  453. void debugmem_list_add(MEMHDR *p)
  454. {
  455.      p->mh_next = memlist;
  456.      p->mh_prev = NULL;
  457.      if (memlist) memlist->mh_prev = p;
  458.      memlist = p;
  459. #ifdef MEM_LIST_DEBUG
  460.      if (stderr)
  461.      Mem_Display(stderr);
  462. #endif
  463. }
  464. void debugmem_list_delete(MEMHDR *p)
  465. {
  466.      if (p->mh_next)
  467.      p->mh_next->mh_prev = p->mh_prev;
  468.      if (p->mh_prev)
  469.      p->mh_prev->mh_next = p->mh_next;
  470.      else memlist = p->mh_next;
  471. #ifdef MEM_LIST_DEBUG
  472.      if (stderr)
  473.      Mem_Display(stderr);
  474. #endif
  475. }
  476. #endif
  477. /*
  478.  * debugmem_tag_error : internal error function.
  479.  */
  480.  
  481. void debugmem_tag_error(void *p)
  482. {
  483.      fprintf(stderr, "Memory tag error occurs :%p nt byen", p);
  484. #ifdef MEM_LIST
  485.      if (stderr)
  486.      xmlMemDisplay(stderr);
  487. #endif
  488. }
  489. FILE *xmlMemoryDumpFile = NULL;
  490. /**
  491.  * xmlMemoryDump:
  492.  *
  493.  * Dump in-extenso the memory blocks allocated to the file .memorylist
  494.  */
  495. void
  496. xmlMemoryDump(void)
  497. {
  498. #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
  499.     FILE *dump;
  500.     dump = fopen(".memdump", "w");
  501.     if (dump == NULL) xmlMemoryDumpFile = stdout;
  502.     else xmlMemoryDumpFile = dump;
  503.     xmlMemDisplay(xmlMemoryDumpFile);
  504.     if (dump != NULL) fclose(dump);
  505. #endif
  506. }
  507. /****************************************************************
  508.  * *
  509.  * Initialization Routines *
  510.  * *
  511.  ****************************************************************/
  512. #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
  513. xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
  514. xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
  515. xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
  516. xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
  517. #else
  518. xmlFreeFunc xmlFree = (xmlFreeFunc) free;
  519. xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
  520. xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
  521. xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) strdup;
  522. #endif
  523. /**
  524.  * xmlInitMemory:
  525.  *
  526.  * Initialize the memory layer.
  527.  *
  528.  * Returns 0 on success
  529.  */
  530. static int xmlInitMemoryDone = 0;
  531. int
  532. xmlInitMemory(void)
  533. {
  534.      int ret;
  535.      
  536. #ifdef HAVE_STDLIB_H
  537.      char *breakpoint;
  538. #endif     
  539.      if (xmlInitMemoryDone) return(-1);
  540. #ifdef HAVE_STDLIB_H
  541.      breakpoint = getenv("XML_MEM_BREAKPOINT");
  542.      if (breakpoint != NULL) {
  543.          sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
  544.      }
  545. #endif     
  546.     
  547. #ifdef DEBUG_MEMORY
  548.      fprintf(stderr, "xmlInitMemory() Okn");
  549. #endif     
  550.      ret = 0;
  551.      return(ret);
  552. }
  553. /**
  554.  * xmlMemSetup:
  555.  * @freeFunc: the free() function to use
  556.  * @mallocFunc: the malloc() function to use
  557.  * @reallocFunc: the realloc() function to use
  558.  * @strdupFunc: the strdup() function to use
  559.  *
  560.  * Override the default memory access functions with a new set
  561.  * This has to be called before any other libxml routines !
  562.  *
  563.  * Should this be blocked if there was already some allocations
  564.  * done ?
  565.  *
  566.  * Returns 0 on success
  567.  */
  568. int
  569. xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
  570.             xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
  571.     if (freeFunc != NULL)
  572. return(-1);
  573.     if (mallocFunc != NULL)
  574. return(-1);
  575.     if (reallocFunc != NULL)
  576. return(-1);
  577.     if (strdupFunc != NULL)
  578. return(-1);
  579.     xmlFree = freeFunc;
  580.     xmlMalloc = mallocFunc;
  581.     xmlRealloc = reallocFunc;
  582.     xmlMemStrdup = strdupFunc;
  583.     return(0);
  584. }
  585. /**
  586.  * xmlMemGet:
  587.  * @freeFunc: the free() function in use
  588.  * @mallocFunc: the malloc() function in use
  589.  * @reallocFunc: the realloc() function in use
  590.  * @strdupFunc: the strdup() function in use
  591.  *
  592.  * Return the memory access functions set currently in use
  593.  *
  594.  * Returns 0 on success
  595.  */
  596. int
  597. xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
  598.   xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
  599.     if (freeFunc != NULL) *freeFunc = xmlFree;
  600.     if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
  601.     if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
  602.     if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
  603.     return(0);
  604. }