home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / debug-utils / safemem / mem.c next >
C/C++ Source or Header  |  1991-07-04  |  7KB  |  291 lines

  1. #include "exec/types.h"
  2. #include "exec/memory.h"
  3. #include "stdio.h"
  4.  
  5. /*
  6.  * FILE:
  7.  *   mem.c
  8.  *
  9.  * DESCRIPTION:
  10.  *     Replacement functions for AllocMem() and FreeMem() that provide
  11.  *  enhanced error checking. These functions put a safety net around the
  12.  *  Amiga's memory allocation routines. They manage their own list,
  13.  *  watching for memory leaks, double frees, etc. safe_AllocMem() and
  14.  *  safe_FreeMem() are functional replacements for AllocMem() and
  15.  *  FreeMem(), while safe_ShowMemList() displays the memory blocks
  16.  *  (and where in the sourcecode they were allocated) that have not
  17.  *  yet been freed.
  18.  *
  19.  *     To convert a program to using these safe calls (which would probably
  20.  *   only be used in the development stage), simply include the .h file,
  21.  *   link the .o file, and place a call to safe_ShowMemList() and
  22.  *   safe_ClearMemList before the program terminates.
  23.  *
  24.  *
  25.  * USAGE:
  26.  *     All access to the functions in this module are accessed via the
  27.  *   macros in mem.h. Once mem.h is included into the source, all calls
  28.  *   to AllocMem() and FreeMem() are replaced with safe_AllocMem() and
  29.  *   safe_FreeMem().
  30.  *
  31.  *     Since safe_ShowMemList() and safe_ClearMemList() are not present in
  32.  *   the normal OS, it is not compatible with s/ware not using the safe_
  33.  *   functions. A simple setup is thus:
  34.  *
  35.  * #ifdef DEBUG
  36.  * #include "mem.h"
  37.  * #endif
  38.  *
  39.  * main()
  40.  * {
  41.  *   ...
  42.  *   ...
  43.  * #ifdef DEBUG
  44.  *   ShowMemList()
  45.  *   ClearMemList()
  46.  * #endif
  47.  * }
  48.  *
  49.  *     The calls to ShowMemList() & ClearMemList() could easily be placed
  50.  *  in a break or exit trap, so that memory was automatically displayed &
  51.  *  freed when the program used an exit(), or the user pressed ^C or ^D.
  52.  *
  53.  */
  54.  
  55.  
  56. /*
  57.  * STRUCT:
  58.  *   MemNode
  59.  *
  60.  * DESCRIPTION:
  61.  *     The MemNode structure is placed at the start of each memory block
  62.  *   managed by the safe_ functions. It contains useful information like
  63.  *   where in the source the block was allocated, how big the block is
  64.  *   and the next block in the list.
  65.  *
  66.  * USAGE:
  67.  *     It is completely internal to the safe_ suite of functions, no other
  68.  *   source need know of it's existance.
  69.  */
  70.  
  71. struct MemNode
  72. {
  73.   struct MemNode *child;             /* Next block in list        */
  74.  
  75.   char *file;                        /* File that allocated us    */
  76.   ULONG line;                        /* Line we were allocated on */
  77.  
  78.   ULONG size;                        /* Size of memory block      */
  79. };
  80.  
  81. static struct MemNode *head;
  82.  
  83. /*
  84.  * FUNCTION:
  85.  *   void *safe_AllocMem(Size, MemType, File, Line)
  86.  *
  87.  * DESCRIPTION:
  88.  *     Peforms a call to AllocMem() with enhanced error checking. Access
  89.  *   to this function should be through the macros in mem.h -ONLY-.
  90.  *   Note that all memory allocated with the safe_ functions must be freed
  91.  *   with the safe_ functions.
  92.  *
  93.  * ARGUMENTS:
  94.  *   long Size;      Size of the block to allocate.
  95.  *   long MemType;   Type of memory to request.
  96.  *   char *File;     Calling file     (ie __FILE__)
  97.  *   int  Line;      Calling line     (ie __LINE__)
  98.  *
  99.  * RETURNS:
  100.  *   SUCCESS: A pointer to the new memory block
  101.  *   FAILURE: 0
  102.  *
  103.  * WRITTEN:
  104.  *   Friday 14-Dec-90 13:02:11 spb
  105.  */
  106.  
  107. void *safe_AllocMem(Size, MemType, File, Line)
  108. ULONG Size;
  109. ULONG MemType;
  110. char *File;
  111. ULONG Line;
  112. {
  113.   struct MemNode *t;
  114.  
  115.   if(head)
  116.     t = head;
  117.   else
  118.     t = 0;
  119.  
  120.   head = AllocMem(Size + sizeof(struct MemNode), MemType);
  121.  
  122.   if(head)
  123.   {
  124.     head->child = t;
  125.     head->file  = File;
  126.     head->line  = Line;
  127.     head->size  = Size;
  128.  
  129.     return((void *)((long)head + sizeof(struct MemNode)));
  130.   }
  131.  
  132.   return(0);
  133. }
  134.  
  135. /*
  136.  * FUNCTION:
  137.  *   void safe_FreeMem(Address, Size, File, Line)
  138.  *
  139.  * DESCRIPTION:
  140.  *     Peforms a FreeMem() with the enhanced error checking. Must be accessed
  141.  *   through the macros in mem.h. Note that all memory allocated with the
  142.  *   safe_ functions must be freed with the safe_ functions.
  143.  *
  144.  * ARGUMENTS:
  145.  *   ULONG Address; Location of block to free
  146.  *   ULONG Size;    Size of block to free
  147.  *   char *File;    Calling file     (__FILE__)
  148.  *   ULONG Line;    Calling line     (__LINE__)
  149.  *
  150.  * WRITTEN:
  151.  *   Friday 14-Dec-90 13:02:20 spb
  152.  */
  153.  
  154. void safe_FreeMem(Address, Size, File, Line)
  155. ULONG Address;
  156. ULONG Size;
  157. char *File;
  158. ULONG Line;
  159. {
  160.   struct MemNode *t1, *t2;
  161.  
  162.   t1 = head;
  163.   t2 = 0;
  164.  
  165.   while(t1)
  166.   {
  167.     if(Address == (long)t1+sizeof(struct MemNode))
  168.     {
  169.       if(Size != t1->size)
  170.       {
  171.         fprintf(stdout, "%s %d: Incorrect free size. (%d instead of %d)\n",
  172.                    File, Line, Size, t1->size);
  173.  
  174.         return;
  175.       }
  176.  
  177.  
  178.       if(t2)
  179.         t2->child = t1->child; /* Remove block from the list */
  180.       else
  181.         head = t1->child;
  182.  
  183.       FreeMem(t1, sizeof(struct MemNode)+t1->size);
  184.       return;
  185.     }
  186.  
  187.     t2 = t1;
  188.     t1 = t1->child;
  189.   }
  190.  
  191.   fprintf(stdout, "%s %d: Free twice (?) FreeMem($%lx, %d)\n",
  192.                    File, Line,                   Address, Size);
  193.  
  194.   return;
  195. }
  196.  
  197. /*
  198.  * FUNCTION:
  199.  *   ULONG safe_ShowMemList(File, Line)
  200.  *
  201.  * DESCRIPTION:
  202.  *     Displays a list of currently unfreed blocks (if there are any) that
  203.  *   were allocated with safe_AllocMem. Along with each memory block
  204.  *   is the file, function and line it was allocated from.
  205.  *
  206.  * ARGUMENTS:
  207.  *   char *File;    Calling File (__FILE__)
  208.  *   char *Line;    Calling Line (__LINE__)
  209.  *
  210.  * RETURNS:
  211.  *   ULONG   Number of memoryblocks in the list.
  212.  *
  213.  * WRITTEN:
  214.  *   Friday 14-Dec-90 13:02:26 spb
  215.  */
  216.  
  217. ULONG safe_ShowMemList(File, Line)
  218. char *File;
  219. char *Line;
  220. {
  221.   ULONG c=0;
  222.   struct MemNode *t;
  223.  
  224.   if(head)
  225.   {
  226.     t = head;
  227.     fprintf(stdout, "%s %d: Memory List\n", File, Line);
  228.  
  229.     fprintf(stdout, "    %-12s %-12s %-16s %-4s\n",
  230.            "Address", "Size", "File", "Line");
  231.     fprintf(stdout, "    %-12s %-12s %-16s %-4s\n",
  232.            "-------", "----", "----", "----");
  233.  
  234.     while(t)
  235.     {
  236.       fprintf(stdout, "    $%-11lx %-12d %-16s %-4d\n",
  237.               t, t->size, t->file, t->line);
  238.  
  239.       t = t->child;
  240.       c++;
  241.     }
  242.   }
  243.   return(c);
  244. }
  245.  
  246. /*
  247.  * FUNCTION:
  248.  *   ULONG safe_ClearMemList(File, Line)
  249.  *
  250.  * DESCRIPTION:
  251.  *     Frees all the memoryblocks present in the safe_ list. This ensures
  252.  *   the environment will get all it's memory back even though the program
  253.  *   is faulty, speeding development time.
  254.  *
  255.  * ARGUMENTS:
  256.  *   char *File; Calling file (__FILE__)
  257.  *   char *Line; Calling line (__LINE__)
  258.  *
  259.  * RETURNS:
  260.  *   long Number of blocks freed.
  261.  *
  262.  * WRITTEN:
  263.  *   Friday 14-Dec-90 13:52:16 spb
  264.  */
  265.  
  266. ULONG safe_ClearMemList(File, Line)
  267. char *File;
  268. char *Line;
  269. {
  270.   ULONG c=0;
  271.   struct MemNode *t1, *t2;
  272.  
  273.   if(head)
  274.   {
  275.     t1 = head;
  276.     fprintf(stdout, "%s %d: Freeing Memory List\n", File, Line);
  277.  
  278.     while(t1)
  279.     {
  280.       t2 = t1->child;
  281.       FreeMem(t1, t1->size + sizeof(struct MemNode));
  282.       t1 = t2;
  283.       c++;
  284.     }
  285.   }
  286.  
  287.   head = 0;
  288.   return(c);
  289. }
  290.  
  291.