home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / unix / aix / 12909 < prev    next >
Encoding:
Text File  |  1992-12-29  |  9.9 KB  |  331 lines

  1. Newsgroups: comp.unix.aix
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!sun-barr!ames!agate!dog.ee.lbl.gov!hellgate.utah.edu!asylum.cs.utah.edu!bytheway
  3. From: bytheway%asylum.cs.utah.edu@cs.utah.edu (Sidney Bytheway)
  4. Subject: Re: memory leak detection
  5. Date: 29 Dec 92 11:27:53 MST
  6. Message-ID: <1992Dec29.112753.3407@hellgate.utah.edu>
  7. Organization: University of Utah CS Dept
  8. References: <2423@sdrc.COM>
  9. Lines: 320
  10.  
  11. In article <2423@sdrc.COM> crgreg@rios1.sdrc.com (Greg Marion) writes:
  12. >I would like to know if anyone has heard of any software that would assist
  13. >developers in detecting when an application allocates memory and does
  14. >not free it. We would have to know which routine/function and maybe
  15. >a range of line numbers that are suspect.
  16. >
  17. >Thanks
  18.  
  19.  
  20. I wrote a malloc wrapper that increased the size of the malloc so I could
  21. 1) chain all of my malloced memory together, 2) tack on an informative string
  22. 3) attach a structure printing function, 4) check for storage violations.
  23. The malloc wrapper returns a pointer to the "data" portion of the malloced
  24. storage to the caller just like malloc.
  25.  
  26. At certain places I call a checking routing that will run through all of the
  27. malloced memory and check for storage violations and, if requested, print the
  28. invormative string and the memory using the printing function.
  29.  
  30. It has proved very useful.  I have included it below.
  31.  
  32. Sid Bytheway
  33.  
  34. ---------------------------------------------------------------------------
  35.   Sid Bytheway, (801) 581-3989    !  Internet: udpsid@snow.usi.utah.edu
  36.   Senior Systems Programmer       !  Bitnet:   UDPSID at UTAHUSI
  37.   Utah Supercomputing Institute   !  US Mail:  150 Park Bldg, SLC, UT 84112
  38. ---------------------------------------------------------------------------
  39.  
  40.  
  41. /***********************************************************************
  42.  *
  43.  *    File:    sid_mem.h
  44.  *    Desc:   Include file for the memory allocation and debugging
  45.  *        routines.  Part of the Support for Improved Development
  46.  *        (SID) library included in the TrISH Migration System.
  47.  *
  48.  *  Copyright:    Sid Bytheway
  49.  *        University of Utah
  50.  *        March 1992
  51.  *
  52.  * This code is supplied "AS IS" with no warranty expressed or implied.
  53.  * Permission to copy, modify, distribute, fold, spindle and mutilate
  54.  * this source code in any way shape or form is hereby granted to everyone.
  55.  * Please include the proper credit.
  56.  *
  57.  ***********************************************************************/
  58.  
  59. #ifndef SID_MEM_H
  60. #define SID_MEM_H
  61.  
  62.  
  63. /*
  64.  * Function Prototypes
  65.  * -------------------
  66.  */
  67. char    *sid_malloc(long size, char *desc, int (*prtfunc)() );
  68. int     sid_free(char *ptr);
  69. int     sid_memscan(int print_flag);
  70.  
  71.  
  72. /*
  73.  * If we are not in DEBUG mode, over-ride all my memory allocation stuff
  74.  * ---------------------------------------------------------------------
  75.  */
  76. #ifndef _DEBUG_
  77.  
  78. #define sid_malloc(size, desc, prtfunc) malloc(size)
  79. #define sid_free(ptr) free(ptr)
  80. #define sid_memscan(print_flag)   FALSE
  81.  
  82. #endif /* _DEBUG_ */
  83.  
  84.  
  85. /*
  86.  * Macro Definitions
  87.  * -----------------
  88.  *
  89.  * Allocates memory for a new object of type objtype.
  90.  *
  91.  * Usage: ptr = newobj( structure_name );
  92.  *      delobj( ptr );
  93.  */
  94.  
  95. #define    newobj(objtype)    \
  96.     (objtype *) sid_malloc( sizeof(objtype), "objtype Object", NULL )
  97.  
  98. #define    delobj( obj ) \
  99.     sid_free( (char *) obj )
  100.  
  101.  
  102.  
  103. #endif /* SID_MEM_H */
  104.  
  105.  
  106. /***********************************************************************
  107.  *
  108.  *    File:   sid_mem.c
  109.  *    Desc:   Contains memory allocation and debugging routines.
  110.  *        Part of the Support for Improved Development (SID)
  111.  *        library included in the TrISH Migration System.
  112.  *
  113.  *  Copyright:    Sid Bytheway
  114.  *        University of Utah
  115.  *        March 1992
  116.  *
  117.  * This code is supplied "AS IS" with no warranty expressed or implied.
  118.  * Permission to copy, modify, distribute, fold, spindle and mutilate
  119.  * this source code in any way shape or form is hereby granted to everyone.
  120.  * Please include the proper credit.
  121.  *
  122.  * ----------------------------------------------------------------------
  123.  *
  124.  * Memory allocation debugging consists of allocating a little extra memory
  125.  * for pattern checking fields, description string, pointers for printing
  126.  * allocated memory, and the size of the user portion of the memory.
  127.  *
  128.  ***********************************************************************/
  129.  
  130. #ifndef _DEBUG_
  131. # define _DEBUG_        /* required for this file */
  132. #endif /* _DEBUG_ */
  133.  
  134. #include <stdio.h>
  135. #include <signal.h>
  136. #include <sys/types.h>
  137.  
  138. #include "sid.h"
  139. #include "sid_mem.h"
  140.  
  141.  
  142. /*
  143.  * The memory check pattern - Define to anything you like.
  144.  * -------------------------------------------------------
  145.  */
  146. #define    SID_CHECK_PATTERN 0xffabacab    /* storage violation pattern */
  147.  
  148.  
  149. /*
  150.  * This is the structure that glues all memory allocations together.
  151.  * -----------------------------------------------------------------
  152.  */
  153. typedef struct _sid_memstruct {
  154.     struct _sid_memstruct *next;    /* ptr to next memory allocation */
  155.     struct _sid_memstruct *prev;    /* ptr to previous allocation */
  156.     char    *desc;            /* char string description */
  157.     long    usr_size;            /* size of user data */
  158.     int        (* prt_callback)();        /* callback func to print memory */
  159.     long    check1;            /* first check field */
  160.                     /* user data is here */
  161.     long    check2;            /* second check field */
  162. } sid_memstruct;
  163.  
  164.  
  165. /*
  166.  * Global variables used by this file and these routines.
  167.  * ------------------------------------------------------
  168.  */
  169. sid_memstruct *sid_mem_first;    /* first memory allocation */
  170. sid_memstruct *sid_mem_last;    /* last memory allocation */
  171.  
  172.  
  173.  
  174. /*************************************************************
  175.  *
  176.  * sid_malloc()
  177.  *
  178.  *    My memory allocation routine that allocates memory and links
  179.  *    it together with a description, printing function and fields
  180.  *    to check for storage violations.
  181.  *
  182.  *************************************************************/
  183. char *sid_malloc( 
  184.     long    size,        /* size of user data */
  185.     char    *desc,        /* char string description */
  186.     int    (* prtfunc)()    /* callback func to print memory */
  187. )
  188. {
  189.  
  190.     char        *newch;
  191.     sid_memstruct    *new;
  192.     long        *check2;
  193.  
  194.     /* first scan memory to see if anything is hosed */
  195.     sid_memscan( FALSE );
  196.  
  197.     /* allocate requested memory plus enough for tracing structure */
  198.     if( (newch = (char *) malloc( size + sizeof(sid_memstruct))) == NULL ){
  199.     fprintf(stderr, "sid_malloc(): Memory allocation error - %s\n", desc);
  200.     exit( 1 );
  201.     }
  202.     new = (sid_memstruct *) newch;
  203.  
  204.     /* put data into my malloc structure */
  205.     new->usr_size = size;
  206.     new->desc = desc;
  207.     new->prt_callback = prtfunc;
  208.     new->check1 = SID_CHECK_PATTERN;
  209.     check2 = (long *) (newch + size + sizeof(sid_memstruct) - sizeof(long));
  210.     *check2 = SID_CHECK_PATTERN;
  211.  
  212.     /* link this dude in with everyone else */
  213.     new->next = NULL;
  214.     if( sid_mem_last != NULL )
  215.     sid_mem_last->next = new;
  216.     new->prev = sid_mem_last;
  217.     sid_mem_last = new;
  218.     if( sid_mem_first == NULL )
  219.     sid_mem_first = new;
  220.  
  221.     /* return to the user a pointer to his data area */
  222.     return( newch + sizeof(sid_memstruct) - sizeof(long) );
  223.  
  224. }
  225.  
  226.  
  227. /*************************************************************
  228.  *
  229.  * sid_free()
  230.  *
  231.  *    My memory de-allocation routine.  Looks at storage violation
  232.  *    fields for violations, prints a message if it finds one.
  233.  *    Frees user and structure memory.
  234.  *
  235.  *************************************************************/
  236. int sid_free(
  237.     char *usr_data        /* ptr to user data*/
  238. )
  239. {
  240.     sid_memstruct    *ptr;
  241.     long        *check2;
  242.  
  243.     /* Point to real head of allocated memory */
  244.     ptr = (sid_memstruct *) (usr_data - sizeof(sid_memstruct) + sizeof(long));
  245.     check2 = (long *) (usr_data + ptr->usr_size);
  246.  
  247.     /* unlink this dude from everyone else */
  248.     if( ptr->prev == NULL )
  249.     sid_mem_first = ptr->next;
  250.     else
  251.     ptr->prev->next = ptr->next;
  252.  
  253.     if( ptr->next == NULL )
  254.     sid_mem_last = ptr->prev;
  255.     else
  256.     ptr->next->prev = ptr->prev;
  257.  
  258.  
  259.     /* Check storage violation fields */
  260.     if(ptr->check1 != SID_CHECK_PATTERN || *check2 != SID_CHECK_PATTERN) {
  261.     fprintf(stderr, "sid_free: A storage violation has occured!!!\n" );
  262.     fprintf(stderr, "desc = \"%s\"\n", ptr->desc );
  263.     fprintf(stderr, "size = %d,  check1 = %8.8x,  check2 = %8.8x\n",
  264.             ptr->usr_size, ptr->check1, *check2 );
  265.     if( ptr->prt_callback != NULL ) {
  266.         fprintf( stderr, "sid_free: User Data Follows...\n\n" );
  267.         (* ptr->prt_callback)( usr_data );
  268.     }
  269.     fputc( '\n', stderr );
  270.     fprintf( stderr, "Forcing core dump and exit\n" );
  271.     kill( 0, SIGTRAP );
  272.     exit( 1 );
  273.     }
  274.  
  275.     return( free( (char *) ptr) );
  276. }
  277.  
  278.  
  279. /*************************************************************
  280.  *
  281.  * sid_memscan()
  282.  *
  283.  *    Scans all linked together storage looking for storage
  284.  *    violations.  If print_flag is set then runs the callback
  285.  *    routine to print the memory.  Returns 0 if no storage
  286.  *    violations, 1 if any storage violations.
  287.  *
  288.  *************************************************************/
  289. int sid_memscan(
  290.     int print_flag
  291. )
  292. {
  293.     sid_memstruct    *walker;
  294.     char        *usr_data;
  295.     long        *check2;
  296.     int            violation, any_violation=FALSE;
  297.  
  298.  
  299.     for(walker = sid_mem_first; walker != NULL; walker = walker->next) {
  300.  
  301.     violation = FALSE;
  302.     usr_data = ((char *) walker) + sizeof(sid_memstruct) - sizeof(long);
  303.     check2 = (long *) (usr_data + walker->usr_size);
  304.  
  305.     /* Test for storage violation - print messages if so */
  306.     if( walker->check1 != SID_CHECK_PATTERN
  307.     || *check2 != SID_CHECK_PATTERN ) {
  308.         fprintf(stderr, "sid_memscan: A storage violation has occured!!!\n" );
  309.         fprintf(stderr, "desc = \"%s\"\n", walker->desc);
  310.         fprintf(stderr, "size = %d  check1 = %8.8x  check2 = %8.8x\n",
  311.                 walker->usr_size, walker->check1, *check2 );
  312.         fprintf(stderr, "next = %8.8x, prev = %8.8x\n",
  313.                 walker->next, walker->prev);
  314.         violation = TRUE;
  315.         any_violation = TRUE;
  316.     }
  317.  
  318.     /* print the structure if violation or if print flag is set */
  319.     if((violation || print_flag) && walker->prt_callback != NULL) {
  320.         fprintf( stderr, "sid_memscan: User Data Follows...\n\n" );
  321.         (* walker->prt_callback)( usr_data );
  322.     }
  323.     if( violation || (print_flag && walker->prt_callback != NULL))
  324.         fputc( '\n', stderr );
  325.     }
  326.  
  327.     return( any_violation );
  328.  
  329. }
  330.  
  331.