home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / MEM.TXT < prev    next >
Text File  |  1997-07-05  |  9KB  |  218 lines

  1. +++Date last modified: 05-Jul-1997
  2.  
  3.                         Walter Bright's MEM Package
  4.                         ---------------------------
  5.  
  6.  
  7. PREFACE:
  8. --------
  9.  
  10. The files, MEM.H and MEM.C which constitute the MEM package were originally
  11. published in the March-April 1990 edition of Micro Cornucopia magazine, now
  12. sadly out of print.  The files as they appear in SNIPPETS have been edited
  13. somewhat to remove compiler dependencies and correct minor discrepancies.
  14.  
  15. For those who don't already know, Walter Bright is the author of Datalight
  16. Optimum-C, the original optimizing C compiler for PC's.  Through a succession
  17. of sales and acquisitions plus continual improvement by Walter,, his compiler
  18. became Zortech C++ and is now sold as Symantec C++.  As such, it is the only
  19. major PC compiler which can claim single authorship.  It also compiles faster
  20. than most other compilers and is still a market leader in its optimization
  21. technology.
  22.  
  23. Like many other library and ancillary functions unique to Walter's compilers,
  24. the MEM package was originally something he wrote for his own use.  As noted
  25. above, he published it only once but it has been included as an unheralded
  26. "freebie" in Walter's compilers for the past several years.  Walter was kind
  27. enough to grant permission for its inclusion in SNIPPETS beginning with the
  28. April, '94 release.
  29.  
  30.  
  31. WHAT IS MEM?:
  32. -------------
  33.  
  34. MEM is a set of functions used for debugging C pointers and memory allocation
  35. problems.  Quoting Walter, "Symptoms of pointer bugs include: hung machines,
  36. scrambled disks, failures that occur once-in-10,000 iterations, irreprodu-
  37. cible results, and male pattern baldness." After writing MEM for use in
  38. developing his own compiler and tools, he reported that its use reduced
  39. pointer bugs by as much as 75%.  MEM is simple to add to existing programs
  40. and adds little or no overhead.
  41.  
  42.  
  43. USING MEM:
  44. ----------
  45.  
  46. Included in the MEM package is TOOLKIT.H, which isolates compiler and
  47. environmental dependencies.  It should work as-is for most PC compilers and
  48. the Microsoft compiler for SCO Unix.  Other environments may be customized by
  49. writing your own HOST.H file, using the existing definitions in TOOLKIT.H as
  50. examples and modifying the values to match your system.  Using these
  51. techniques, the MEM package has been used successfully on Amigas, Macs,
  52. VAXes, and many other non-DOS systems.
  53.  
  54. The MEM functions exactly parallel the standard library (plus 1 non-standard)
  55. memory allocation functions.  To implement MEM in your program, simply do a
  56. global search-and-replace of the following functions:
  57.  
  58.       malloc()    ->    mem_malloc()
  59.       calloc()    ->    mem_calloc()
  60.       realloc()   ->    mem_realloc()
  61.       free()      ->    mem_free()
  62.       strdup()    ->    mem_strdup()
  63.  
  64. At the beginning of main(), add the following lines:
  65.  
  66.       mem_init();
  67.       atexit(mem_term);
  68.  
  69. In the header section of each of your C files, add...
  70.  
  71. #include "mem.h"
  72.  
  73. ...to every .C file which calls any of the above functions.
  74.  
  75. The final step is to compile and link MEM.C into all programs using the MEM
  76. package.  It really is a pretty simple procedure!
  77.  
  78. MEM has 2 modes of operation, debugging and non-debugging.  Use debugging
  79. mode during program development and then turn debugging off for final
  80. production code.  Control of debugging is by defining the MEM_DEBUG macro.
  81. If the macro is defined, debugging is on; if undefined, debugging is off.
  82. The default is non-debugging, in which case the MEM functions become trivial
  83. wrappers for the standard functions, incurring virtually no overhead.
  84.  
  85.  
  86. WHAT MEM DOES:
  87. --------------
  88.  
  89. 1.    ISO/ANSI verification:
  90.  
  91. When Walter wrote MEM, compiler compliance with ANSI standards was still
  92. quite low.  MEM verifies ISO/ANSI compliance for situations such as passing
  93. NULL or size 0 to allocation/reallocation functions.
  94.  
  95. 2.    Logging of all allocations and frees:
  96.  
  97. All MEM's functions pass the __FILE__ and __LINE__ arguments.  During alloca-
  98. tion, MEM makes an entry into a linked list and stores the file and line
  99. information in the list for whichever allocation or free function is called.
  100.  
  101. This linked list is the backbone of MEM.  When MEM detects a bug, it tells
  102. you where to look in which file to begin tracking the problem.
  103.  
  104. 3.    Verification of frees:
  105.  
  106. Since MEM knows about all allocations, when a pointer is freed, MEM can
  107. verify that the pointer was allocated originally.  Additionally, MEM will
  108. only allow a pointer to be freed once.
  109.  
  110. Freed data is overwritten with a non-zero known value, flushing such problems
  111. as continuing to reference data after it's been freed.  The value written
  112. over the data is selected to maximize the probability of a segment fault or
  113. assertion failure if your application references it after it's been freed.
  114.  
  115. MEM obviously can't directly detect "if" instances such as...
  116.  
  117.       mem_free(p);
  118.       if (p) ...
  119.  
  120. ...but by guaranteeing that `p' points to garbage after being freed, code
  121. like this will hopefully never work and will thus be easier to find.
  122.  
  123. 4.    Detection of pointer over- and under-run:
  124.  
  125. Pointer overrun occurs when a program stores data past the end of a buffer,
  126. e.g.
  127.  
  128.       p = malloc(strlen(s));        /* No space for terminating NUL      */
  129.       strcpy(p,s);                  /* Terminating NUL clobber memory   */
  130.  
  131. Pointer underrun occurs when a program stores data before the beginning of a
  132. buffer.  This error occurs less often than overruns, but MEM detects it
  133. anyway.  MEM does this by allocating a little extra at each end of every
  134. buffer, which is filled with a known value, called a sentinel. MEM detects
  135. overruns and underruns by verifying the sentinel value when the buffer is
  136. freed.
  137.  
  138. 5.    Dependence on values in buffer obtained from malloc():
  139.  
  140. When obtaining a buffer from malloc(), a program may develop erroneous and
  141. creeping dependencies on whatever random (and sometimes repeatable) values
  142. the buffer may contain.  The mem_malloc() function prevents this by always
  143. setting the data in a buffer to a known non-zero value before returning its
  144. pointer.  This also prevents another common error when running under MS-DOS
  145. which doesn't clear unused memory when loading a program.  These bugs are
  146. particularly nasty to find since correct program operation may depend on what
  147. was last run!
  148.  
  149. 6.    Realloc problems:
  150.  
  151. Common problems when using realloc() are: 1) depending on realloc() *not*
  152. shifting the location of the buffer in memory, and 2) depending on finding
  153. certain values in the uninitialized region of the realloc'ed buffer.
  154.  
  155. MEM flushes these out by *always* moving the buffer and stomping on values
  156. past the initialized area.
  157.  
  158. 7.    Memory leak detection:
  159.  
  160. Memory "leaks" are areas that are allocated but never freed.  This can become
  161. a major problem in programs that must run for long periods without interrup-
  162. tion (e.g. BBS's).  If there are leaks, eventually the program will run out
  163. of memory and fail.
  164.  
  165. Another form of memory leak occurs when a piece of allocated memory should
  166. have been added to some central data structure, but wasn't.
  167.  
  168. MEM find memory leaks by keeping track of all allocations and frees.  When
  169. mem_term() is called, a list of all unfreed allocations is printed along with
  170. the files and line numbers where the allocations occurred.
  171.  
  172. 8.    Pointer checking:
  173.  
  174. Sometimes it's useful to be able to verify that a pointer is actually
  175. pointing into free store. MEM provides a function...
  176.  
  177.       mem_checkptr(void *p);
  178.  
  179. ...to do this.
  180.  
  181. 9.    Consistency checking:
  182.  
  183. Occasionally, even MEM's internal data structures get clobbered by a wild
  184. pointer.  When this happens, you can track it down by sprinkling your code
  185. temporarily with calls to mem_check(), which performs a consistency check on
  186. the free store.
  187.  
  188. 10.   Out of memory handling:
  189.  
  190. MEM can be set using mem_setexception() (see MEM.H) to handle out-of-memory
  191. conditions in any one of several predefined ways:
  192.  
  193.       1.    Present an "Out of memory" message and terminate the program.
  194.       2.    Abort the program with no message.
  195.       3.    Mimic ISO/ANSI and return NULL.
  196.       4.    Call a user-specified function, perhaps involving virtual memory
  197.             or some other "emergency reserve".
  198.       5.    Retry (be careful to avoid infinite loops!)
  199.  
  200. 11.   Companion techniques:
  201.  
  202. Since MEM presets allocated and stomps on freed memory, this facilitates
  203. adding your own code to add tags to your data structures when debugging.  If
  204. the structures are invalid, you'll know it because MEM will have clobbered
  205. your verification tags.
  206.  
  207.  
  208. SUMMARY:
  209. --------
  210.  
  211. Since it is, in the final analysis, a software solution, MEM is fallible.  As
  212. the saying goes, "Nothing is foolproof because fools are so ingenious."
  213. Walter himself readily acknowledges that there are circumstances where your
  214. code can do sufficient damage to MEM's internal data structures to render it
  215. useless.  The good news is such circumstances are few and far between.  For
  216. most memory debugging, MEM is a highly reliable and valuable addition to your
  217. C programming toolchest.
  218.