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