memory.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:18k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * FILE:    memory.c
  3.  * AUTHORS:  Isidor Kouvelas / Colin Perkins / Mark Handley / Orion Hodson
  4.  *
  5.  * $Revision: 1.5 $
  6.  * $Date: 2002/06/12 17:37:25 $
  7.  *
  8.  * Copyright (c) 1995-2000 University College London
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, is permitted provided that the following conditions 
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions and the following disclaimer.
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in the
  18.  *    documentation and/or other materials provided with the distribution.
  19.  * 3. All advertising materials mentioning features or use of this software
  20.  *    must display the following acknowledgement:
  21.  *      This product includes software developed by the Computer Science
  22.  *      Department at University College London
  23.  * 4. Neither the name of the University nor of the Department may be used
  24.  *    to endorse or promote products derived from this software without
  25.  *    specific prior written permission.
  26.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38. #include "config_unix.h"
  39. #include "config_win32.h"
  40. #include "debug.h"
  41. #include "memory.h"
  42. #include "util.h"
  43. #ifdef DEBUG_MEM
  44. /* Custom memory routines are here, down to #else, defaults follow */
  45. #define MAX_ADDRS         65536
  46. #define MAGIC_MEMORY      0xdeadbeef
  47. #define MAGIC_MEMORY_SIZE 4
  48. /* Allocated block format is:
  49.  * <chk_header> <memory chunk...> <trailing magic number>
  50.  */
  51. typedef struct {
  52.         uint32_t key;   /* Original allocation number   */
  53.         uint32_t size;  /* Size of allocation requested */
  54.         uint32_t pad;   /* Alignment padding to 8 bytes */
  55.         uint32_t magic; /* Magic number                 */
  56. } chk_header;
  57. typedef struct s_alloc_blk {
  58.         uint32_t    key;     /* Key in table (ascending) */
  59.         chk_header *addr;
  60.         char       *filen;   /* file where allocated     */
  61.         int         line;    /* line where allocated     */
  62.         size_t      length;  /* size of allocation       */
  63.         int         blen;    /* size passed to block_alloc (if relevent) */
  64.         int         est;     /* time last touched in order of all allocation and reclaims */
  65. } alloc_blk;
  66. /* Table is ordered by key */
  67. static alloc_blk mem_item[MAX_ADDRS];
  68. static int   naddr = 0; /* number of allocations */
  69. static int   tick  = 1; /* xmemchk assumes this is one, do not change without checking why */
  70. static int   init  = 0;
  71. /**
  72.  * xdoneinit:
  73.  * @void: 
  74.  * 
  75.  * Marks end of an applications initialization period.  For media
  76.  * applications with real-time data transfer it's sometimes helpful to
  77.  * distinguish between memory allocated during application
  78.  * initialization and when application is running.
  79.  **/
  80. void xdoneinit(void) 
  81. {
  82. init = tick++;
  83. }
  84. extern int chk_header_okay(const chk_header *ch);
  85. int chk_header_okay(const chk_header *ch)
  86. {
  87.         const uint8_t *tm; /* tail magic */
  88.         ASSERT(ch != NULL);
  89.         if (ch->key == MAGIC_MEMORY) {
  90.                 fprintf(stderr, "ERROR: freed unit being checkedn");
  91.                 abort();
  92.         }
  93.         tm = (const uint8_t*)ch;
  94.         tm += sizeof(chk_header) + ch->size;
  95.         if (ch->magic != MAGIC_MEMORY) {
  96.                 fprintf(stderr, "ERROR: memory underrunn");
  97.                 abort();
  98.                 return FALSE;
  99.         } else if (memcmp(tm, &ch->magic, MAGIC_MEMORY_SIZE)) {
  100.                 fprintf(stderr, "ERROR: memory overrunn");
  101.                 abort();
  102.                 return FALSE;
  103.         }
  104.         return TRUE;
  105. }
  106. static int mem_key_cmp(const void *a, const void *b) {
  107.         const alloc_blk *g, *h;
  108.         g = (const alloc_blk*)a;
  109.         h = (const alloc_blk*)b;
  110.         if (g->key < h->key) {
  111.                 return -1;
  112.         } else if (g->key > h->key) {
  113.                 return +1;
  114.         }
  115.         return 0;
  116. }
  117. static alloc_blk *mem_item_find(uint32_t key) {
  118.         void      *p;
  119.         alloc_blk  t;
  120.         t.key = key;
  121.         p = bsearch((const void*)&t, mem_item, naddr, sizeof(alloc_blk), mem_key_cmp);
  122.         return (alloc_blk*)p;
  123. }
  124. /**
  125.  * xmemchk:
  126.  * @void: 
  127.  * 
  128.  * Check for bounds overruns in all memory allocated with xmalloc(),
  129.  * xrealloc(), and xstrdup().  Information on corrupted blocks is
  130.  * rendered on the standard error stream.  This includes where the
  131.  * block was allocated, the size of the block, and the number of
  132.  * allocations made since the block was created.
  133.  **/
  134. void xmemchk(void)
  135. {
  136.         uint32_t    last_key;
  137.         chk_header *ch;
  138.         int         i;
  139. if (naddr > MAX_ADDRS) {
  140. fprintf(stderr, "ERROR: Too many addresses for xmemchk()!n");
  141. abort();
  142. }
  143.         last_key = 0;
  144. for (i = 0; i < naddr; i++) {
  145.                 /* Check for table corruption */
  146.                 if (mem_item[i].key  < last_key) {
  147.                         fprintf(stderr, "Memory table keys out of order - fatal error");
  148.                         abort();
  149.                 }
  150.                 last_key = mem_item[i].key;
  151.                 if (mem_item[i].addr == NULL) {
  152.                         fprintf(stderr, "Memory table entry reference null block - fatal error");
  153.                         abort();
  154.                 }
  155.                 if (mem_item[i].filen == NULL) {
  156.                         fprintf(stderr, "Memory table filename missing - fatal error");
  157.                         abort();
  158.                 }
  159.                 if ((size_t) strlen(mem_item[i].filen) != mem_item[i].length) {
  160.                         fprintf(stderr, "Memory table filename length corrupted - fatal error");
  161.                         abort();
  162.                 }
  163.                 
  164.                 /* Check memory */
  165.                 ch = mem_item[i].addr;
  166.                 if (chk_header_okay(ch) == FALSE) {
  167.                         /* Chk header display which side has gone awry */
  168. fprintf(stderr, "Memory check failed!n");
  169. fprintf(stderr, "addr: %p", mem_item[i].addr);
  170.                         fprintf(stderr, "  size: %6d", ch->size);
  171.                         fprintf(stderr, "  age: %6d", tick - mem_item[i].est);
  172.                         fprintf(stderr, "  file: %s", mem_item[i].filen);
  173.                         fprintf(stderr, "  line: %d", mem_item[i].line);
  174.                         fprintf(stderr, "n");
  175.                         abort();
  176.                 }
  177.         }
  178. }
  179. static int 
  180. alloc_blk_cmp_origin(const void *vab1, const void *vab2)
  181. {
  182.         const alloc_blk *ab1, *ab2;
  183.         int sc;
  184.         
  185.         ab1 = (const alloc_blk*)vab1;
  186.         ab2 = (const alloc_blk*)vab2;
  187.         if (ab1->filen == NULL || ab2->filen == NULL) {
  188.                 if (ab1->filen == NULL && ab2->filen == NULL) {
  189.                         return 0;
  190.                 } else if (ab1->filen == NULL) {
  191.                         return +1;
  192.                 } else /* (ab2->filen == NULL)*/ {
  193.                         return -1;
  194.                 }
  195.         }
  196.         sc = strcmp(ab1->filen, ab2->filen);
  197.         if (sc == 0) {
  198.                 if (ab1->line > ab2->line) {
  199.                         return +1;
  200.                 } else if (ab1->line == ab2->line) {
  201.                         return 0;
  202.                 } else /* (ab1->line < ab2->line) */{
  203.                         return -1;
  204.                 }
  205.         }
  206.         return sc;
  207. }
  208. static int
  209. alloc_blk_cmp_est(const void *vab1, const void *vab2)
  210. {
  211.         const alloc_blk *ab1, *ab2;
  212.         ab1 = (const alloc_blk*)vab1;        
  213.         ab2 = (const alloc_blk*)vab2;
  214.         
  215.         if (ab1->est > ab2->est) {
  216.                 return +1;
  217.         } else if (ab1->est == ab2->est) {
  218.                 return 0;
  219.         } else {
  220.                 return -1;
  221.         }
  222. }
  223. /**
  224.  * xmemdmp:
  225.  * @void: 
  226.  * 
  227.  * Dumps the address, size, age, and point of allocation in code.
  228.  *
  229.  **/
  230. void 
  231. xmemdmp(void)
  232. {
  233. int i;
  234.         block_release_all();
  235. if (naddr > MAX_ADDRS) {
  236. printf("ERROR: Too many addresses for xmemdmp()!n");
  237. abort();
  238. }
  239.         qsort(mem_item, naddr, sizeof(mem_item[0]), alloc_blk_cmp_est);
  240.         for (i=0; i<naddr; i++) {
  241.                 printf("%5d",i);                               fflush(stdout);
  242.                 printf("  addr: %p", mem_item[i].addr);        fflush(stdout);
  243.                 printf("  size: %5d", mem_item[i].addr->size); fflush(stdout);
  244.                 printf("  age: %6d", tick - mem_item[i].est);  fflush(stdout);
  245.                 printf("  file: %s", mem_item[i].filen);       fflush(stdout);
  246.                 printf(":%d", mem_item[i].line);               fflush(stdout);
  247.                 if (mem_item[i].blen != 0) { 
  248.                         printf("  tblen %d", mem_item[i].blen);   
  249.                         fflush(stdout);
  250.                 }
  251.                 printf("n");
  252.         }
  253. printf("Program initialisation finished at age %6dn", tick-init);
  254.         qsort(mem_item, naddr, sizeof(mem_item[0]), mem_key_cmp);
  255. }
  256. /* Because block_alloc recycles blocks we need to know which code
  257.  * fragment takes over responsibility for the memory.  */
  258. /**
  259.  * xclaim:
  260.  * @addr: address
  261.  * @filen: new filename
  262.  * @line: new allocation line
  263.  * 
  264.  * Coerces information in allocation table about allocation file and
  265.  * line to be @filen and @line.  This is used by the evil
  266.  * block_alloc() and should probably not be used anywhere else ever.
  267.  **/
  268. void 
  269. xclaim(void *addr, const char *filen, int line)
  270. {
  271.         alloc_blk *m;
  272.         chk_header *ch;
  273.         
  274.         ch = ((chk_header *)addr) - 1;
  275.         m  = mem_item_find(ch->key); 
  276.         if (chk_header_okay(ch) == FALSE) {
  277.                 fprintf(stderr, "xclaim: memory corruptedn");
  278.                 abort();
  279.         }
  280.         if (m == NULL) {
  281.                 fprintf(stderr, "xclaim: block not foundn");
  282.                 abort();
  283.         }
  284.         free(m->filen);
  285.         m->filen  = strdup(filen);
  286.         m->length = strlen(filen);
  287.         m->line   = line;
  288.         m->est    = tick++;
  289. }
  290. /**
  291.  * xmemdist:
  292.  * @fp: file pointer
  293.  * 
  294.  * Dumps information on existing memory allocations to file.
  295.  **/
  296. void 
  297. xmemdist(FILE *fp)
  298. {
  299.         int i, last_line=-1, cnt=0, entry=0;
  300.         char *last_filen = NULL;
  301.         /* This is painful...I don't actually envisage running beyond this dump :-)
  302.          * 2 sorts are needed, one into order by file, and then back to key order.
  303.          */
  304.         qsort(mem_item, naddr, sizeof(mem_item[0]), alloc_blk_cmp_origin);
  305.         fprintf(fp, "# Distribution of memory allocatedn# <idx> <file> <line> <allocations>n");
  306.         for(i = 0; i < naddr; i++) {
  307.                 if (last_filen == NULL ||
  308.                     last_line  != mem_item[i].line ||
  309.                     strcmp(last_filen, mem_item[i].filen)) {
  310.                         if (last_filen != NULL) {
  311.                                 fprintf(fp, "% 3dn", cnt);
  312.                         }
  313.                         cnt = 0;
  314.                         last_filen = mem_item[i].filen;
  315.                         last_line  = mem_item[i].line;
  316.                         fprintf(fp, "% 3d %20s % 4d ", entry, last_filen, last_line);
  317.                         entry++;
  318.                 }
  319.                 cnt++;
  320.         }
  321.         fprintf(fp, "% 3dn", cnt);
  322.         /* Restore order */
  323.         qsort(mem_item, naddr, sizeof(mem_item[0]), mem_key_cmp);
  324. }
  325. /**
  326.  * xfree:
  327.  * @p: pointer to block to freed.
  328.  * 
  329.  * Free block of memory.  Semantically equivalent to free(), but
  330.  * checks for bounds overruns in @p and tidies up state associated
  331.  * additional functionality.
  332.  *
  333.  * Must be used to free memory allocated with xmalloc(), xrealloc(),
  334.  * and xstrdup().
  335.  **/
  336. void 
  337. xfree(void *p)
  338. {
  339.         alloc_blk  *m;
  340.         chk_header *ch;
  341.         uint32_t size, delta, magic, idx;
  342.         
  343. if (p == NULL) {
  344. printf("ERROR: Attempt to free NULL pointer!n");
  345. abort();
  346. }
  347.         ch = ((chk_header*)p) - 1;
  348.         printf("free at %pn", ch);
  349.         /* Validate entry  */
  350.         if (chk_header_okay(ch) == FALSE) {
  351.                 printf("ERROR: Freeing corrupted blockn");
  352.                 abort();
  353.         }
  354.         /* Locate in table */
  355.         m = mem_item_find(ch->key);
  356.         if (m == NULL) {
  357.                 printf("ERROR: Freeing unallocated or already free'd blockn");
  358.                 abort();
  359.         }
  360.         /* Trash memory of allocated block, maybe noticed by apps when    
  361.          * deref'ing free'd */
  362.         size  = ch->size + sizeof(chk_header) + MAGIC_MEMORY_SIZE;
  363.         magic = MAGIC_MEMORY;
  364.         p     = (uint8_t*)ch;
  365.         while (size > 0) {
  366.                 delta = min(size, 4);
  367.                 memcpy(p, &magic, delta);
  368.                 (uint8_t*)p += delta;
  369.                 size        -= delta;
  370.         }
  371.         /* Free memory     */
  372.         free(ch);
  373.         free(m->filen);
  374.         /* Remove from table */
  375.         idx = m - mem_item;
  376.         if (naddr - idx > 0) {
  377.                 memmove(&mem_item[idx], 
  378.                         &mem_item[idx + 1], 
  379.                         (naddr - idx - 1) * sizeof(alloc_blk));
  380.         }
  381.         naddr--;
  382.         xmemchk();
  383. }
  384. void *
  385. _xmalloc(unsigned size, const char *filen, int line)
  386. {
  387.         uint32_t   *data;
  388.         void       *p;
  389.         chk_header *ch;
  390.         p = (void*) malloc (size + sizeof(chk_header) + MAGIC_MEMORY_SIZE);
  391. ASSERT(p     != NULL);
  392. ASSERT(filen != NULL);
  393.         /* Fix block header */
  394.         ch = (chk_header*)p;
  395.         ch->key   = tick++;
  396.         ch->size  = size;
  397.         ch->magic = MAGIC_MEMORY;
  398. data = (uint32_t*)((chk_header *)p + 1);
  399. #if 0
  400. memset((void*)data, 0xf0, size);
  401. #else
  402. memset((void*)data, 0, size);
  403. #endif
  404.         
  405.         /* Fix block tail */
  406.         memcpy(((uint8_t*)data) + size, &ch->magic, MAGIC_MEMORY_SIZE);
  407.         /* Check set up okay */
  408.         if (chk_header_okay(ch) == FALSE) {
  409.                 fprintf(stderr, "Implementation Errorn");
  410.                 abort();
  411.         }
  412.         /* Add table entry */
  413.         mem_item[naddr].key    = ch->key;
  414. mem_item[naddr].addr   = p;
  415. mem_item[naddr].filen  = (char *)strdup(filen);
  416. mem_item[naddr].line   = line;
  417. mem_item[naddr].length = strlen(filen);
  418.         mem_item[naddr].blen   = 0;        /* block_alloc'ed len when appropriate     */
  419.         mem_item[naddr].est    = ch->key;  /* changes when block_alloc recycles block */
  420.         naddr ++;
  421. if (naddr >= MAX_ADDRS) {
  422. fprintf(stderr, "ERROR: Allocated too much! Table overflow in xmalloc()n");
  423. fprintf(stderr, "       Do you really need to allocate more than %d items?n", MAX_ADDRS);
  424. abort();
  425. }
  426.         
  427.         if (chk_header_okay(ch) == FALSE) {
  428.                 fprintf(stderr, "Implementation Errorn");
  429.                 abort();
  430.         }
  431.         printf("malloc at %pn", p);
  432.         return (uint8_t*)p + sizeof(chk_header);
  433. }
  434. void *
  435. _xrealloc(void *p, unsigned size, const char *filen, int line)
  436. {
  437.         alloc_blk  *m;
  438.         chk_header *ch;
  439.         uint8_t    *t;
  440.        
  441.         ASSERT(p     != NULL);
  442.         ASSERT(filen != NULL);
  443.         ch = ((chk_header*) p) - 1;
  444.         m  = mem_item_find(ch->key);
  445.         if (m != NULL) {
  446.                 /* Attempt reallocation */
  447.                 m->addr = realloc((void*)ch, size + sizeof(chk_header) + MAGIC_MEMORY_SIZE);
  448.                 if (m->addr == NULL) {
  449.                         debug_msg("realloc failedn");
  450.                         return NULL;
  451.                 }
  452.                 /* Update table */
  453.                 free(m->filen);
  454.                 m->filen  = (char *) strdup(filen);
  455.                 m->line   = line;
  456.                 m->length = strlen(filen);
  457.                 m->est    = tick++;
  458.                 /* Fix chunk header */
  459.                 ch->size  = size;
  460.                 /* Fix trailer */
  461.                 t = (uint8_t*)p + size;
  462.                 memcpy(t, &ch->magic, MAGIC_MEMORY_SIZE);
  463.                 /* Check block is okay */
  464.                 if (chk_header_okay(ch) == FALSE) {
  465.                         fprintf(stderr, "Implementation Errorn");
  466.                         abort();
  467.                 }
  468.                 return p;
  469. }
  470. debug_msg("Trying to xrealloc() memory not which is not allocatedn");
  471. abort();
  472.         return 0;
  473. }
  474. char *_xstrdup(const char *s1, const char *filen, int line)
  475. {
  476. char  *s2;
  477.   
  478. s2 = (char *) _xmalloc(strlen(s1)+1, filen, line);
  479. if (s2 != NULL) {
  480. strcpy(s2, s1);
  481.         }
  482. return (s2);
  483. }
  484. #else
  485. void xdoneinit (void) { return; }
  486. void xmemchk   (void) { return; }
  487. void xmemdmp   (void) { return; }
  488. void xclaim    (void *p, const char *filen, int line)
  489. {
  490.         UNUSED(p);
  491.         UNUSED(filen);
  492.         UNUSED(line);
  493.         return;
  494. }
  495. void xmemdist (FILE *f) { UNUSED(f); }
  496. void xfree    (void *x) { free(x); }
  497. void *_xmalloc(unsigned int size, const char *filen, int line) {
  498. void *m;
  499. m = malloc(size);
  500. #ifdef DEBUG
  501. /* This is just to check initialization errors in allocated structs */
  502. memset(m, 0xf0, size);
  503. #endif
  504. UNUSED(filen);
  505. UNUSED(line);
  506. return m;
  507. }
  508. void *_xrealloc(void *p, unsigned int size,const char *filen,int line) {
  509.         UNUSED(filen);
  510.         UNUSED(line);
  511.         return realloc(p, size);
  512. }
  513. char *_xstrdup(const char *s1, const char *filen, int line) {
  514.         UNUSED(filen);
  515.         UNUSED(line);
  516.         return strdup(s1);
  517. }
  518. #endif /* DEBUG_MEM */