home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj8908.zip / MERILATT.LST < prev    next >
File List  |  1989-07-06  |  9KB  |  287 lines

  1. C DYNAMIC MEMORY USE
  2. by Randall Merilatt
  3.  
  4.  
  5. [LISTIN╟ ONE]
  6.  
  7. /*---------------------------------------------------------------
  8.    xmem.c -- Extended Dynamic Memory Control Module.
  9. ---------------------------------------------------------------*/
  10. /* ********************** INCLUDE FILES ********************** */
  11. #include <stdio.h>
  12.  
  13. /* ******************** EXTERNAL FUNCTIONS ******************* */
  14. extern char *malloc(unsigned int);
  15. extern char *calloc(unsigned int, unsigned int);
  16. extern void  free(char *);
  17.  
  18. /* ********************* GLOBAL FUNCTIONS ******************** */
  19. char *x_malloc(unsigned int);
  20. char *x_calloc(unsigned int, unsigned int);
  21. void  x_free(char *);
  22. void  x_chkfree();
  23.  
  24. /* ********************* GLOBAL VARIABLES ******************** */
  25. /* memtrace usage:
  26.       = 0 => simple calls to malloc & free
  27.       = 1 => tracking of all allocations using hash table
  28.       = 2 => checking for changes to previously freed blocks
  29. */
  30. int  memtrace   = 1;     /* memory tracing control variable */
  31. long tot_memory = 0L;    /* total amount of allocated memory */
  32. long tot_alloc  = 0L;    /* total # of allocations */
  33. int  hashsize   = 47;    /* size of hash table */
  34. int  bucketsize = 10;    /* number of entries per hash bucket */
  35.  
  36. /* ********************* LOCAL VARIABLES ********************* */
  37. /* memory allocation tracking table */
  38.  
  39. /* amount of extra allocation for overhead */
  40. #define OVHDSIZE 2
  41.  
  42. /* fill character for overhead gap */
  43. #define FILLCHAR '\377'
  44.  
  45. /* allocated entry information */
  46. typedef struct alloc_entry {
  47.    int   size;           /* size of allocated area */
  48.    char *ptr;            /* pointer to allocated area */
  49.    char *freed;          /* pointer to copy of allocated area */
  50. } ALLOCATION;
  51.  
  52. typedef struct bucket {
  53.    struct bucket *next;  /* pointer to next bucket when filled */
  54.    int entries;          /* number of used entries */
  55.    ALLOCATION *alloc;    /* allocated entry array */
  56. } BUCKET;
  57.  
  58. #define NUL_BUCKET ((BUCKET *)0)
  59. è/* dynamic pointer hash table */
  60. static BUCKET **ptrhash = (BUCKET **)0;
  61.  
  62. /* ==============================================================
  63.    Store pointer in hash table
  64. */
  65. static char *sto_ptr(p, b)
  66. char *p;     /* pointer to be stored */
  67. unsigned b;  /* size of area */
  68. {
  69.    register BUCKET *bp, *bq;    /* bucket pointers */
  70.    register int bno;            /* bucket/entry number */
  71.  
  72.    if ( ! ptrhash ) {
  73.       /* allocate pointer hash table */
  74.       ptrhash = (BUCKET **)calloc(hashsize, sizeof(BUCKET *));
  75.       if ( ! ptrhash )
  76.          return(NULL);
  77.       tot_memory = hashsize * sizeof(BUCKET *);
  78.    }
  79.    /* compute hash table index */
  80.    bno = (int)((unsigned long)p % hashsize);
  81.  
  82.    /* find first bucket with available entries */
  83.    for (bq = bp = ptrhash[bno]; bp && bp->entries == bucketsize;
  84.       bp = bp->next)
  85.       bq = bp;
  86.  
  87.    /* allocate new bucket if necessary */
  88.    if ( bp == NUL_BUCKET ) {
  89.       if ( ! (bp = (BUCKET *)malloc(sizeof(BUCKET))) )
  90.          return(NULL);
  91.       bp->next = NUL_BUCKET;
  92.       bp->entries = 0;
  93.       if ( bq )
  94.          /* connect to end of bucket chain */
  95.          bq->next = bp;
  96.       else
  97.          /* initial bucket for this hash entry */
  98.          ptrhash[bno] = bp;
  99.  
  100.       /* allocate bucket's allocation entry array */
  101.       bp->alloc = (ALLOCATION *)calloc(bucketsize,
  102.                      sizeof(ALLOCATION));
  103.  
  104.       /* memory total includes space used by hash table */
  105.       tot_memory += sizeof(BUCKET) +
  106.                        bucketsize*sizeof(ALLOCATION);
  107.    }
  108.    /* store pointer to allocated block */
  109.    bno = bp->entries++;
  110.    bp->alloc[bno].ptr   = p;
  111.    bp->alloc[bno].freed = NULL;
  112.    bp->alloc[bno].size  = b;
  113. è   /* update total allocation */
  114.    tot_memory += b;
  115.  
  116.    /* increment total number of allocations */
  117.    ++tot_alloc;
  118.  
  119.    return(p);
  120. }
  121.  
  122. /* ==============================================================
  123.    Delete pointer from hash table
  124. */
  125. static void del_ptr(p)
  126. char *p;  /* pointer to be freed */
  127. {
  128.    int gap;                     /* index into overhead space */
  129.    register BUCKET *bp, *bq;    /* bucket pointers */
  130.    register int bno, i;         /* bucket/entry number */
  131.  
  132.    /* compute hash table index */
  133.    bno = (int)((unsigned long)p % hashsize);
  134.  
  135.    /* search bucket(s) for pointer */
  136.    for (bq = NUL_BUCKET, bp = ptrhash[bno]; bp; bp = bp->next) {
  137.       for ( i = 0; i < bp->entries; ++i ) {
  138.          if ( bp->alloc[i].ptr == p ) {
  139.             /* check integrity of gap */
  140.             for (gap=bp->alloc[i].size-OVHDSIZE;
  141.                gap<bp->alloc[i].size; ++gap ) {
  142.                if ( p[gap] != FILLCHAR ) {
  143.                   printf("WARNING overwrite, addr: %lx\n",
  144.                      (long)p);
  145.                   break;
  146.                }
  147.             }
  148.             if ( memtrace == 1 ) {
  149.                /* remove entry from bucket */
  150.                if ( --bp->entries == 0 ) {
  151.                   /* free this bucket */
  152.                   if ( bq )
  153.                      bq->next = bp->next;
  154.                   else
  155.                      ptrhash[bno] = bp->next;
  156.                   free((char *)bp->alloc);
  157.                   free((char *)bp);
  158.                   tot_memory -= (sizeof(BUCKET) +
  159.                                   bucketsize*sizeof(ALLOCATION));
  160.                }
  161.                else if ( i < bp->entries ) {
  162.                   /* move last entry into current spot */
  163.                   bp->alloc[i] = bp->alloc[bp->entries];
  164.                }
  165.                free(p);
  166.             }
  167.             else {è               /* memtrace == 2
  168.                   => save copy to check for bad mods */
  169.                if ( bp->alloc[i].freed )
  170.                   printf("WARNING freeing free ptr, addr: %lx\n",
  171.                      (long)p);
  172.                else if (bp->alloc[i].freed = malloc(bp->alloc[i].size))
  173.                   memcpy(bp->alloc[i].freed, bp->alloc[i].ptr,
  174.                      bp->alloc[i].size);
  175.  
  176.             }
  177.             /* update total allocated memory count */
  178.             tot_memory -= bp->alloc[i].size;
  179.  
  180.             /* normal return */
  181.             return;
  182.          }
  183.       }
  184.       bq = bp;
  185.    }
  186.    if ( ! bp )
  187.       printf("WARNING freeing bad pointer, addr: %lx\n", (long)p);
  188. }
  189.  
  190. /* ==============================================================
  191.    Allocate b bytes of memory
  192. */
  193. char *x_malloc( b )
  194. unsigned int b;  /* number of bytes to allocate */
  195. {
  196.    register char *mptr;
  197.    
  198.    if ( memtrace ) {
  199.       /* add gap space */
  200.       b += OVHDSIZE;
  201.  
  202.       /* allocate memory */
  203.       if ( mptr = malloc(b) ) {
  204.          /* fill gap */
  205.          memset(mptr+b-OVHDSIZE, FILLCHAR, OVHDSIZE);
  206.  
  207.          /* store mptr in ptrhash */
  208.          mptr = sto_ptr(mptr, b);
  209.       }
  210.    }
  211.    else
  212.       mptr = malloc(b);
  213.  
  214.    return(mptr);
  215.  
  216. /* ==============================================================
  217.    Allocate and clear i*s bytes of memory
  218. */
  219. char *x_calloc( i, s )
  220. unsigned int i; /* number of blocks to be allocated */èunsigned int s; /* size (in bytes) of each block */
  221. {
  222.    register unsigned int amt;
  223.    register char *mptr;
  224.    
  225.    /* allocate requested space */
  226.    if ( mptr = x_malloc(amt = i*s) ) {
  227.       /* clear requested space */
  228.       memset(mptr, '\0', amt);
  229.    }
  230.    return (mptr);
  231.  
  232. /* ==============================================================
  233.    Free allocated memory
  234. */
  235. void x_free( p )
  236. char *p; /* pointer to block to be freed */
  237. {
  238.    if ( p == NULL )
  239.       printf("WARNING freed a null pointer\n");
  240.    else if ( memtrace )
  241.       del_ptr(p);
  242.    else
  243.       free((char *)p);
  244. }
  245.  
  246. /* ==============================================================
  247.    Check to ensure all blocks have been freed
  248. */
  249. void x_chkfree()
  250. {
  251.    ALLOCATION *ap;              /* allocation entry pointer */
  252.    register int bno, i;         /* bucket/entry number */
  253.    register BUCKET *bp, *bq;    /* bucket pointers */
  254.  
  255.    if ( memtrace ) {
  256.       /* check for unfreed variables */
  257.       for ( bno = 0; bno < hashsize; ++bno ) {
  258.          for ( bp = ptrhash[bno]; bp; bp = bq ) {
  259.             for (i = 0; i < bp->entries; ++i) {
  260.                ap = &bp->alloc[i];
  261.                if ( memtrace == 2 && ap->freed ) {
  262.                   /* check for changes to freed blocks */
  263.                   if ( memcmp(ap->ptr, ap->freed, ap->size) )
  264.                      printf("WARNING block chgd after free, addr: %lx\n",
  265.                         (long)ap->ptr);
  266.                }
  267.                /* free unfreed block */
  268.                printf("WARNING freeing unfreed block, addr: %lx\n",
  269.                   (long)ap->ptr);
  270.                free(ap->ptr);
  271.             }
  272.             bq = bp->next;
  273. è            /* free bucket */
  274.             free((char *)bp->alloc);
  275.             free((char *)bp);
  276.          }
  277.       }
  278.       /* free pointer hash pointer array */
  279.       free((char *)ptrhash);
  280.       ptrhash = (BUCKET **)0;
  281.  
  282.       tot_memory = 0L;
  283.    }
  284. }
  285.