home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 322_01 / readme.mal < prev    next >
Text File  |  1990-08-06  |  7KB  |  169 lines

  1.               Malloc Leak Trace Package
  2.  
  3.                  by Michael Schwartz
  4.          University of Washington Computer Science Department
  5.                Seattle, Washington, USA
  6.             schwartz@cs.washington.edu  (ARPANET)
  7.            schwartz%cs.washington.edu@relay.cs.net  (CSNET)
  8.         ...{allegra,caip,ihnp4,nike}!uw-beaver!schwartz  (UUCP)
  9.  
  10.                   April 1987
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18. 1. Description
  19.  
  20. This package is designed to help trace dynamic memory allocation leaks.
  21. It works by providing the standard malloc/free/realloc interface, but at
  22. the same time keeping track of all malloc'd buffers, including their size,
  23. order of call, and address.  That way, at any point during the execution of
  24. your program, you can see what malloc'd buffers haven't yet been freed.
  25. It is particularly useful when your program performs many allocations
  26. before reaching some steady state, and hence you want to ignore
  27. the initial allocations and concentrate on where steady-state
  28. leaks occur.
  29.  
  30. The idea is that you have some code (usually a server) that looks as follows:
  31.     initialization code;
  32.     do {
  33.         ...
  34.     } while (1); /* main loop */
  35.  
  36. There might be some dynamic allocation during the initialization,
  37. but this isn't where the memory leak is, since it's a one-shot allocation
  38. (i.e., at worst the initialization wastes some memory, but doesn't
  39. continually leak it).  There might also be some dynamic allocation in
  40. the first few iterations of the main loop, until a "steady state" is
  41. reached (e.g., until some cache gets filled).  In both cases (initialization
  42. and pre-steady state iterations), there may be many allocation calls, but
  43. you don't really want to look at them; rather, you want to look at what
  44. memory isn't being free'd once steady state has been reached.  This
  45. package helps you to see the state of memory allocation after steady
  46. state has been reached.
  47.  
  48. Bug reports and suggestions for improvements are welcome.
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56. 2. Instructions
  57.  
  58. To use this package, take your favorite malloc/free/realloc code,
  59. and change the routine names as follows:
  60.  
  61.     malloc -> mmalloc
  62.     free -> ffree
  63.     realloc -> rrealloc
  64.  
  65. You'll probably also need to add the following line to the beginning of
  66. your malloc.c:
  67.  
  68.     char *malloc();
  69.  
  70. (because realloc still calls malloc, but malloc is no longer defined in
  71. that file).  Then link the program to be leak-traced with maltrace.o,
  72. btree.o, and (your modified) malloc.o.  I would have included my malloc.c,
  73. but it's the copyrighted BSD 4.3 code, and besides, there are plenty
  74. of public domain malloc's available (e.g., in volume 6 of mod.sources).
  75.  
  76. To trace a leak, take the example program skeleton, and augment it as
  77. follows:
  78.     extern int MalTraceEnbld;
  79.     extern int MalBrkNum;
  80.     initialization code;
  81.     do {
  82.         ...
  83.         if ( steady state reached)
  84.             MalTraceEnbld = 1;
  85.         ...
  86.         at end of first steady-state cycle:
  87.             PMal(-10);    /* print last 10 (say) malloc's
  88.                        that haven't yet been free'd */
  89.     } while (1); /* main loop */
  90.  
  91. Then compile the program with -g, and run it.  At the end of the first
  92. cycle, PMal will print a list of the last 10 malloc's that haven't yet been
  93. freed.  (PMal(n) will print the first n entries if n > 0, the last -n
  94. entries if n < 0, and all entries if n == 0).  Note the sequence number of
  95. one of these mallocs, and then go into dbx on the program, and put a
  96. breakpoint somewhere in the initialization code, and run the program.  When
  97. you hit the breakpoint, use dbx to set MalBrkNum to the number of the
  98. malloc you just noticed, and set a break in MalBreak.  Then, continue the
  99. program.  When the malloc call in question is reached, MalBreak will get
  100. called, breaking, and giving you a chance to examine the state of the
  101. program at the time of this (potentially leaking) malloc call.  In case
  102. this call is still within the steady-state setup (it is sometimes difficult
  103. to find where the setup ends), you can use dbx to call NextMal, to set
  104. MakBrkNum to be the next traced malloc call.
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112. 2.1 Usage Details
  113.  
  114. This technique is not applicable to situations where the steady state
  115. allocation behavior (i.e., order and size of malloc requests) exhibits
  116. variation, e.g., due to pseudo-randomization or interaction with other
  117. processes via non-deterministically ordered message exchanges.  In such
  118. situations you can sometimes inhibit the variation during debugging (e.g.,
  119. by forcing interactions to occur in the same order each time).
  120. Alternatively, you can use dbx to set MalBreakSize to be the size of the
  121. malloc request at which to have MalBreak called, to reach a breakpoint
  122. (similar to the MalBrkNum scheme described above).  This can be useful when
  123. the order of mallocs isn't fixed, but a particular size keeps showing up in
  124. the list of malloc's that haven't yet been free'd.
  125.  
  126. There is also a routine called UntracedFree that gets called when a free
  127. call is made on an address that was not malloc'd with tracing enabled
  128. (again, this routine is present to allow one to set dbx breakpoints for
  129. this event).  This could either indicate a free call on an address that
  130. isn't malloc'd (a bug) or a free call on an address that was malloc'd with
  131. tracing disabled.  You can determine if it was of the former nature by
  132. going through the standard malloc code.  For example, in the BSD code, you
  133. can set the switches -DDEBUG and -DRCHECK to check for this and other
  134. types of bugs.  Alternatively, you can enable tracing from the very
  135. beginning of your program, and then any time UntracedFree gets called, it
  136. indicates a free call on an addresss that isn't malloc'd.
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144. 3. Interactive Demo
  145.  
  146. You can try out this package interactively by making the program 'test'.
  147. Note that if you tell it to free some memory that was not malloc'd (with
  148. MalTraceEnbld = 1), it will give you a warning and then try to free the
  149. address anyway (for the reasons explained earlier).  This may or may not
  150. cause malloc/free to get into a bad state; in BSD malloc this can cause a
  151. core dump, for instance.
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159. 4. Acknoledgements, History
  160.  
  161. Thanks to Richard Hellier from the University of Kent at Canterbury
  162. (rlh@ukc.UUCP) for the btree package (which I modified slightly for the
  163. current package).  I probably could have implemented my trace package more
  164. efficiently than it works currently (e.g., by incorporating the linked-list
  165. and btree nodes into the malloc header nodes), but I was more into hacking
  166. something together quickly that would solve my problems than making
  167. efficient code.  Besides, this code doesn't need to be efficient, since
  168. it's only plugged in during debugging.
  169.