home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3487 / debugalloc.c next >
Encoding:
C/C++ Source or Header  |  1991-06-15  |  8.8 KB  |  423 lines

  1. /* $Header: /home/hyperion/mu/christos/src/mine/lib/alloc/RCS/debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $ */
  2. /*
  3.  *
  4.  * debugalloc.c : Special Debug Malloc Routines
  5.  *
  6.  * Routines:
  7.  *    char *         DebugMalloc();
  8.  *    char *        DebugCalloc();
  9.  *    char *        DebugRealloc();
  10.  *    void         DebugFree();
  11.  *    unsigned    DebugMemStat();
  12.  *    unsigned    DebugMemPtr();
  13.  *    void        DebugMemChain();
  14.  *
  15.  * $Log: debugalloc.c,v $
  16.  * Revision 1.4  1991/05/05  02:49:43  christos
  17.  * Fixed small lint bug
  18.  *
  19.  * Revision 1.3  1991/04/21  00:14:18  christos
  20.  * Fixed free error message
  21.  *
  22.  * Revision 1.2  1991/02/10  00:44:07  christos
  23.  * Added tests for pointers out of the allocated
  24.  * range
  25.  *
  26.  * Revision 1.1  1991/02/01  08:12:55  christos
  27.  * Initial revision
  28.  *
  29.  */
  30. #ifndef lint
  31. static char rcsid[] = "$Id: debugalloc.c,v 1.4 1991/05/05 02:49:43 christos Exp $";
  32. #endif /* lint */
  33. #include <stdio.h>
  34.  
  35. #ifdef __STDC__
  36. # include <stdlib.h>
  37. # include <memory.h>
  38. #else
  39. extern char *malloc();
  40. extern char *calloc();
  41. extern char *realloc();
  42. extern void free();
  43. extern void abort();
  44. extern char *memset();
  45. extern void exit();
  46. #endif
  47.  
  48. #ifndef NIL
  49. # define NIL(a) ((a *) 0)
  50. #endif /* NIL */
  51.  
  52. #ifndef MIN
  53. # define MIN(a, b)         ((a) > (b) ? (b) : (a))
  54. #endif /* MIN */
  55.  
  56. #ifndef MAX
  57. # define MAX(a, b)         ((a) < (b) ? (b) : (a))
  58. #endif /* MAX */
  59.  
  60. #ifndef private
  61. # define private static
  62. #endif /* private */
  63.  
  64. #ifndef public
  65. # define public 
  66. #endif /* public */
  67.  
  68. #define SIG_GOOD    0x01020304
  69. #define SIG_FREE    0x04030201
  70. #define SIG_CHAIN    0x44332211
  71. #define OVERHEAD    sizeof(debug_t)
  72.  
  73.  
  74. #ifdef __STDC__
  75. typedef    void *Ptr;
  76. #else
  77. typedef char *Ptr;
  78. #endif
  79.  
  80. typedef struct debug_t {
  81.     long    d_sign;
  82.     unsigned    long d_size;
  83.     char *    d_file;
  84.     long    d_line;
  85.     union {
  86.     struct {
  87.         struct debug_t    *c_prev;
  88.         struct debug_t    *c_next;
  89.     } d_c;
  90.     struct {
  91.         char         *f_file;
  92.         long        f_line;
  93.     } d_f;
  94.     } d_d;
  95. } debug_t;
  96.  
  97. #define d_next        d_d.d_c.c_next
  98. #define d_prev        d_d.d_c.c_prev
  99. #define d_ffile     d_d.d_f.f_file
  100. #define d_fline     d_d.d_f.f_line
  101.  
  102.  
  103.  
  104. private unsigned _memused = 0;
  105. private unsigned _memalloc = 0;
  106. private Ptr     _memtop = (Ptr) 0;
  107. private Ptr     _membot = (Ptr) 0xffffffff;
  108. private debug_t *chain;
  109.  
  110.  
  111. /* _chaini():
  112.  *    Insert block in chain
  113.  */
  114. private debug_t *
  115. _chaini(tptr, n, fname, lineno)
  116. char **tptr;
  117. unsigned n;
  118. char *fname;
  119. int lineno;
  120. {
  121.     static debug_t __chain;
  122.     debug_t *dbg;
  123.  
  124.     dbg = (debug_t *) *tptr;
  125.     *tptr += OVERHEAD;
  126.  
  127.     if (chain == NIL(debug_t)) {
  128.     chain = &__chain;
  129.     chain->d_next = chain->d_prev = chain;
  130.     chain->d_sign = SIG_CHAIN;
  131.     chain->d_size = 0;
  132.     chain->d_file = NIL(char);
  133.     chain->d_line = 0;
  134.     }
  135.     dbg->d_sign = SIG_GOOD;
  136.     dbg->d_size = n;
  137.     dbg->d_file = fname;
  138.     dbg->d_line = lineno;
  139.     dbg->d_next = chain->d_next;
  140.     dbg->d_prev = chain;
  141.     chain->d_next->d_prev = dbg;
  142.     chain->d_next = dbg;
  143.     chain = dbg;
  144.     _memused += chain->d_size;
  145.     _memalloc++;
  146.     return(dbg);
  147. } /* end _chaini */
  148.  
  149.  
  150. /* _chaina():
  151.  *    Allocate a block of the required size
  152.  */
  153. private Ptr
  154. _chaina(n, action, routine, fname, lineno, tptr)
  155. unsigned n;
  156. char *action;
  157. Ptr (*routine)();
  158. char *fname;
  159. int lineno;
  160. Ptr tptr;
  161. {
  162.     char *ptr;
  163.     debug_t *dbg;
  164.  
  165.     if (tptr != (Ptr) 0 && (tptr < _membot || tptr > _memtop || 
  166.     ((int) tptr) & 0x3)) {
  167.     (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n", 
  168.                fname, lineno, action);
  169.     abort();
  170.     }
  171.     if (n == 0) {
  172.     (void) fprintf(stderr, 
  173.                "*** %s, %d: %s zero length block.\n", 
  174.                fname, lineno, action);
  175.     if (tptr != (Ptr) 0) {
  176.         dbg = (debug_t *) tptr;
  177.         (void) _chaini((char **) &tptr, (unsigned) dbg->d_size, 
  178.                dbg->d_file, (int) dbg->d_line);
  179.     }
  180.     abort();
  181.     }
  182.  
  183.     ptr = (tptr == (Ptr) 0) ? (char *) (*routine)(n+OVERHEAD) :
  184.       (*routine)(tptr, n+OVERHEAD);
  185.  
  186.     _memtop = MAX((Ptr) ptr, _memtop);
  187.     _membot = MIN((Ptr) ptr, _membot);
  188.  
  189.     if (ptr == NIL(char)) {
  190.     (void) fprintf(stderr, 
  191.         "*** %s, %d: Out of memory in %s (current allocation %u).\n", 
  192.         fname, lineno, action, n);
  193.     if (tptr != (Ptr) 0) {
  194.         dbg = (debug_t *) tptr;
  195.         (void) _chaini((char **) &tptr, (unsigned) dbg->d_size, 
  196.                dbg->d_file, (int) dbg->d_line);
  197.     }
  198.     abort();
  199.     }
  200.     return((Ptr) ptr);
  201. } /* end _chaina */
  202.  
  203.  
  204. /* _chainf():
  205.  *    Free block in chain
  206.  */
  207. private void
  208. _chainf(dbg, action, fname, lineno)
  209. debug_t *dbg;
  210. char *action;
  211. char *fname;
  212. int lineno;
  213. {
  214.     dbg->d_sign = SIG_FREE;
  215.     if (chain == dbg)
  216.     chain = dbg->d_prev;
  217.     dbg->d_prev->d_next = dbg->d_next;
  218.     dbg->d_next->d_prev = dbg->d_prev;
  219.     dbg->d_ffile = fname;
  220.     dbg->d_fline = lineno;
  221.     _memused -= dbg->d_size;
  222.     _memalloc--;
  223. } /* end _chainf */
  224.  
  225.  
  226. /* _chaing():
  227.  *    Return the debug header of a chain
  228.  */
  229. private debug_t *
  230. _chaing(ptr, action, fname, lineno)
  231. char **ptr;
  232. char *action;
  233. char *fname;
  234. int lineno;
  235. {
  236.     if (*ptr == NIL(char)) {
  237.     (void) fprintf(stderr, "**** %s, %d: %s nil pointer.\n", 
  238.                fname, lineno, action);
  239.     abort();
  240.     }
  241.     *ptr -= OVERHEAD;
  242.     if ((Ptr) *ptr < _membot || (Ptr) *ptr > _memtop || (((long) *ptr) & 0x3)) {
  243.     (void) fprintf(stderr, "*** %s, %d: %s invalid pointer.\n", 
  244.                fname, lineno, action);
  245.     abort();
  246.     }
  247.     return((debug_t *) *ptr);
  248. } /* end _chaing */
  249.  
  250.  
  251.  
  252.  
  253. /* _chainc():
  254.  *    Check block in chain
  255.  */
  256. private void
  257. _chainc(dbg, action, fname, lineno)
  258. debug_t *dbg;
  259. char *action;
  260. char *fname;
  261. int lineno;
  262. {
  263.     static char *msg1 = "*** %s, %d: %s %s block";
  264.     static char *msg2 = " [%s, %d: %s]";
  265.  
  266.     switch (dbg->d_sign) {
  267.     case SIG_GOOD:
  268.     break;
  269.     case SIG_FREE:
  270.         (void) fprintf(stderr, msg1, fname, lineno, action, "freed");
  271.         (void) fprintf(stderr, msg2, dbg->d_file, dbg->d_line, "allocated");
  272.         (void) fprintf(stderr, msg2, dbg->d_ffile, dbg->d_fline, "freed");
  273.     abort();
  274.     break;
  275.     default:
  276.         (void) fprintf(stderr, msg1, fname, lineno, action, "invalid");
  277.     (void) fprintf(stderr, ".\n");
  278.     abort();
  279.     break;
  280.     }
  281. } /* end _chainc */
  282.  
  283.  
  284. /* DebugMalloc():
  285.  *    real alloc 
  286.  */
  287. public Ptr
  288. DebugMalloc(n, fname, lineno)
  289. unsigned n;
  290. char *fname;
  291. int lineno;
  292. {
  293.     static char *routine = "malloc";
  294.     Ptr ptr;
  295.  
  296.     ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
  297.     (void) _chaini((char **) &ptr, n, fname, lineno);
  298.     return(ptr);
  299. } /* end DebugMalloc */
  300.  
  301.  
  302. /* DebugFree():
  303.  *    free memory counting the number of bytes freed
  304.  */
  305. public void
  306. DebugFree(ptr, fname, lineno)
  307. Ptr ptr;
  308. char *fname;
  309. int lineno;
  310. {
  311.     static char *routine = "free";
  312.     debug_t *dbg;
  313.  
  314.     dbg = _chaing((char **) &ptr, routine, fname, lineno);
  315.     _chainc(dbg, routine, fname, lineno);
  316.     _chainf(dbg, routine, fname, lineno);
  317.     free(ptr);
  318. } /* end DebugFree */
  319.  
  320.  
  321. /* DebugMemStat():
  322.  *    return the amount of memory in use
  323.  */
  324. public unsigned
  325. DebugMemStat()
  326. {
  327.     return(_memused);
  328. } /* end DebugMemStat */
  329.  
  330.  
  331. /* DebugMemPtr():
  332.  *    return the amount of memory in use
  333.  */
  334. public unsigned
  335. DebugMemPtr(ptr, fname, lineno)
  336. Ptr ptr;
  337. char *fname;
  338. int lineno;
  339. {
  340.     static char *routine = "get size";
  341.     debug_t *dbg;
  342.  
  343.     dbg = _chaing((char **) &ptr, routine, fname, lineno);
  344.     _chainc(dbg, routine, fname, lineno);
  345.  
  346.     return((unsigned) dbg->d_size);
  347. } /* end DebugMemPtr */
  348.  
  349.  
  350. /* DebugRealloc():
  351.  *    real alloc 
  352.  */
  353. public Ptr
  354. DebugRealloc(ptr, n, fname, lineno)
  355. Ptr ptr;
  356. unsigned n;
  357. char *fname;
  358. int lineno;
  359. {
  360.     static char *routine = "realloc";
  361.     debug_t *dbg;
  362.  
  363.     dbg = _chaing((char **) &ptr, routine, fname, lineno);
  364.     _chainc(dbg, routine, fname, lineno);
  365.     _chainf(dbg, routine, fname, lineno);
  366.     ptr = _chaina(n, routine, realloc, fname, lineno, ptr);
  367.     dbg = _chaini((char **) &ptr, n, fname, lineno);
  368.  
  369.     return(ptr);
  370. } /* end DebugRealloc */
  371.  
  372.  
  373. /* DebugCalloc():
  374.  *    real alloc 
  375.  */
  376. public Ptr
  377. DebugCalloc(n, sz, fname, lineno)
  378. unsigned n, sz;
  379. char *fname;
  380. int lineno;
  381. {
  382.     static char *routine = "calloc";
  383.     Ptr ptr;
  384.  
  385.     n *= sz;
  386.     ptr = _chaina(n, routine, malloc, fname, lineno, (Ptr) 0);
  387.     (void) _chaini((char **) &ptr, n, fname, lineno);
  388.     memset((char *) ptr, 0, n);
  389.     return(ptr);
  390. } /* end DebugCalloc */
  391.  
  392. /* DebugMemChain():
  393.  *    Dump the memory chain
  394.  */
  395. public void
  396. DebugMemChain()
  397. {
  398.     debug_t *dbg;
  399.     unsigned min, max;
  400.  
  401.     max = 0x00000000;
  402.     min = 0xffffffff;
  403.  
  404.     if (chain == NIL(debug_t) || chain->d_sign == SIG_CHAIN) {
  405.     (void) fprintf(stdout, "\tNo memory allocated.\n");
  406.     return;
  407.     }
  408.     (void) fprintf(stdout, "\tMemory Allocation Statistics.\n");
  409.     (void) fprintf(stdout, "\t%u bytes allocated in %u chunks.\n",
  410.            _memused, _memalloc);
  411.     for (dbg = chain; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next);
  412.     (void) fprintf(stdout, "\t%8.8s %8.8s %20.20s %5.5s\n",
  413.            "Address", "Size", "Filename", "Line");
  414.     for (dbg = dbg->d_next; dbg->d_sign != SIG_CHAIN; dbg = dbg->d_next) {
  415.     (void) fprintf(stdout, "\t%.8x %8d %20.20s %5d\n",
  416.                dbg, dbg->d_size, dbg->d_file, dbg->d_line);
  417.     min = MIN(min, dbg->d_size);
  418.     max = MAX(max, dbg->d_size);
  419.     }
  420.     (void) fprintf(stdout, "\tMin %u Max %u Avg %u.\n", 
  421.            min, max, _memused / _memalloc);
  422. } /* end DebugMemChain */
  423.