140266059SGregory Neil Shapiro<html> 240266059SGregory Neil Shapiro<head> 340266059SGregory Neil Shapiro <title>libsm : Memory Allocation</title> 440266059SGregory Neil Shapiro</head> 540266059SGregory Neil Shapiro<body> 640266059SGregory Neil Shapiro 740266059SGregory Neil Shapiro<a href="index.html">Back to libsm overview</a> 840266059SGregory Neil Shapiro 940266059SGregory Neil Shapiro<center> 1040266059SGregory Neil Shapiro <h1> libsm : Memory Allocation </h1> 11*4313cc83SGregory Neil Shapiro <br> $Id: heap.html,v 1.9 2000-12-08 21:41:42 ca Exp $ 1240266059SGregory Neil Shapiro</center> 1340266059SGregory Neil Shapiro 1440266059SGregory Neil Shapiro<h2> Introduction </h2> 1540266059SGregory Neil Shapiro 1640266059SGregory Neil ShapiroThe heap package provides a layer of abstraction on top of 1740266059SGregory Neil Shapiro<tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt> 1840266059SGregory Neil Shapirothat provides optional error checking and memory leak detection, 1940266059SGregory Neil Shapiroand which optionally raises an exception when an allocation request 2040266059SGregory Neil Shapirocannot be satisfied. 2140266059SGregory Neil Shapiro 2240266059SGregory Neil Shapiro<h2> Synopsis </h2> 2340266059SGregory Neil Shapiro 2440266059SGregory Neil Shapiro<pre> 2540266059SGregory Neil Shapiro#include <sm/heap.h> 2640266059SGregory Neil Shapiro 2740266059SGregory Neil Shapiro/* 2840266059SGregory Neil Shapiro** Wrappers for malloc, realloc, free 2940266059SGregory Neil Shapiro*/ 3040266059SGregory Neil Shapirovoid *sm_malloc(size_t size); 3140266059SGregory Neil Shapirovoid *sm_realloc(void *ptr, size_t size); 3240266059SGregory Neil Shapirovoid sm_free(void *ptr); 3340266059SGregory Neil Shapiro 3440266059SGregory Neil Shapiro/* 3540266059SGregory Neil Shapiro** Wrappers for malloc, realloc that raise an exception instead of 3640266059SGregory Neil Shapiro** returning NULL on heap exhaustion. 3740266059SGregory Neil Shapiro*/ 3840266059SGregory Neil Shapirovoid *sm_malloc_x(size_t size); 3940266059SGregory Neil Shapirovoid *sm_realloc_x(void *ptr, size_t size); 4040266059SGregory Neil Shapiro 4140266059SGregory Neil Shapiro/* 4240266059SGregory Neil Shapiro** Print a list of currently allocated blocks, 4340266059SGregory Neil Shapiro** used to diagnose memory leaks. 4440266059SGregory Neil Shapiro*/ 4540266059SGregory Neil Shapirovoid sm_heap_report(FILE *stream, int verbosity); 4640266059SGregory Neil Shapiro 4740266059SGregory Neil Shapiro/* 4840266059SGregory Neil Shapiro** Low level interfaces. 4940266059SGregory Neil Shapiro*/ 5040266059SGregory Neil Shapiroint sm_heap_group(); 5140266059SGregory Neil Shapiroint sm_heap_setgroup(int g); 5240266059SGregory Neil Shapiroint sm_heap_newgroup(); 5340266059SGregory Neil Shapirovoid *sm_malloc_tagged(size_t size, char *file, int line, int group); 5440266059SGregory Neil Shapirovoid *sm_malloc_tagged_x(size_t size, char *file, int line, int group); 5540266059SGregory Neil Shapirobool sm_heap_register(void *ptr, size_t size, char *file, int line); 5640266059SGregory Neil Shapiro</pre> 5740266059SGregory Neil Shapiro 5840266059SGregory Neil Shapiro<h2> How to allocate and free memory </h2> 5940266059SGregory Neil Shapiro 6040266059SGregory Neil Shapiro <tt>sm_malloc</tt>, <tt>sm_realloc</tt> and <tt>sm_free</tt> 6140266059SGregory Neil Shapiro are portable plug in replacements 6240266059SGregory Neil Shapiro for <tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt> that provide 6340266059SGregory Neil Shapiro error checking and memory leak detection. 6440266059SGregory Neil Shapiro <tt>sm_malloc_x</tt> and <tt>sm_realloc_x</tt> 6540266059SGregory Neil Shapiro are variants of 6640266059SGregory Neil Shapiro <tt>sm_malloc</tt> and <tt>sm_realloc</tt> 6740266059SGregory Neil Shapiro that raise an exception on error. 6840266059SGregory Neil Shapiro To use the package effectively, 6940266059SGregory Neil Shapiro all calls to <tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt> 7040266059SGregory Neil Shapiro should be replaced by calls 7140266059SGregory Neil Shapiro to the corresponding <tt>sm_</tt>* routines. 7240266059SGregory Neil Shapiro 7340266059SGregory Neil Shapiro<dl> 7440266059SGregory Neil Shapiro<dt> 7540266059SGregory Neil Shapiro<tt> void *sm_malloc(size_t size) </tt> 7640266059SGregory Neil Shapiro<dd> 7740266059SGregory Neil Shapiro This function is a plug-in replacement for <tt>malloc</tt>. 7840266059SGregory Neil Shapiro It allocates <tt>size</tt> bytes of memory on the heap 7940266059SGregory Neil Shapiro and returns a pointer to it, 8040266059SGregory Neil Shapiro or it returns <tt>NULL</tt> on failure. 8140266059SGregory Neil Shapiro <p> 8240266059SGregory Neil Shapiro 8340266059SGregory Neil Shapiro The C standard says that <tt>malloc(0)</tt> may return 8440266059SGregory Neil Shapiro either <tt>NULL</tt> or a non-<tt>NULL</tt> value. 8540266059SGregory Neil Shapiro To ensure consistent behaviour on all platforms, 8640266059SGregory Neil Shapiro <tt>sm_malloc(0)</tt> is equivalent to <tt>sm_malloc(1)</tt>. 8740266059SGregory Neil Shapiro <p> 8840266059SGregory Neil Shapiro 8940266059SGregory Neil Shapiro In addition, if heap checking is enabled, then <tt>sm_malloc</tt> 9040266059SGregory Neil Shapiro maintains a hash table describing all currently allocated 9140266059SGregory Neil Shapiro memory blocks. This table is used for argument validity 9240266059SGregory Neil Shapiro checking in <tt>sm_realloc</tt> and <tt>sm_free</tt>, 9340266059SGregory Neil Shapiro and it can be printed using <tt>sm_heap_report</tt> 9440266059SGregory Neil Shapiro as an aid to finding memory leaks. 9540266059SGregory Neil Shapiro <p> 9640266059SGregory Neil Shapiro 9740266059SGregory Neil Shapiro<dt> 9840266059SGregory Neil Shapiro<tt> void *sm_malloc_x(size_t size) </tt> 9940266059SGregory Neil Shapiro<dd> 10040266059SGregory Neil Shapiro This function is just like <tt>sm_malloc</tt> 10140266059SGregory Neil Shapiro except that it raises the <tt>SmHeapOutOfMemory</tt> exception 10240266059SGregory Neil Shapiro instead of returning <tt>NULL</tt> on error. 10340266059SGregory Neil Shapiro <p> 10440266059SGregory Neil Shapiro 10540266059SGregory Neil Shapiro<dt> 10640266059SGregory Neil Shapiro<tt> void *sm_realloc(void *ptr, size_t size) </tt> 10740266059SGregory Neil Shapiro<dd> 10840266059SGregory Neil Shapiro This function is a plug-in replacement for <tt>realloc</tt>. 10940266059SGregory Neil Shapiro If <tt>ptr</tt> is null then this call is equivalent 11040266059SGregory Neil Shapiro to <tt>sm_malloc(size)</tt>. 11140266059SGregory Neil Shapiro Otherwise, the size of the object pointed to by <tt>ptr</tt> 11240266059SGregory Neil Shapiro is changed to <tt>size</tt> bytes, and a pointer to the 11340266059SGregory Neil Shapiro (possibly moved) object is returned. 11440266059SGregory Neil Shapiro If the space cannot be allocated, then the object pointed to 11540266059SGregory Neil Shapiro by <tt>ptr</tt> is unchanged and <tt>NULL</tt> is returned. 11640266059SGregory Neil Shapiro <p> 11740266059SGregory Neil Shapiro 11840266059SGregory Neil Shapiro If <tt>size</tt> is 0 then we pretend that <tt>size</tt> is 1. 11940266059SGregory Neil Shapiro This may be a mistake. 12040266059SGregory Neil Shapiro <p> 12140266059SGregory Neil Shapiro 12240266059SGregory Neil Shapiro If ptr is not NULL and heap checking is enabled, 12340266059SGregory Neil Shapiro then ptr is required to be a value that was 12440266059SGregory Neil Shapiro previously returned by sm_malloc or sm_realloc, and which 12540266059SGregory Neil Shapiro has not yet been freed by sm_free. If this condition is not 12640266059SGregory Neil Shapiro met, then the program is aborted using sm_abort. 12740266059SGregory Neil Shapiro <p> 12840266059SGregory Neil Shapiro 12940266059SGregory Neil Shapiro<dt> 13040266059SGregory Neil Shapiro<tt> void *sm_realloc_x(void *ptr, size_t size) </tt> 13140266059SGregory Neil Shapiro<dd> 13240266059SGregory Neil Shapiro This function is just like <tt>sm_realloc</tt> 13340266059SGregory Neil Shapiro except that it raises the SmHeapOutOfMemory exception 13440266059SGregory Neil Shapiro instead of returning <tt>NULL</tt> on error. 13540266059SGregory Neil Shapiro <p> 13640266059SGregory Neil Shapiro 13740266059SGregory Neil Shapiro<dt> 13840266059SGregory Neil Shapiro<tt> void sm_free(void *ptr) </tt> 13940266059SGregory Neil Shapiro<dd> 14040266059SGregory Neil Shapiro This function is a plug-in replacement for free. 14140266059SGregory Neil Shapiro If heap checking is disabled, then this function is equivalent 14240266059SGregory Neil Shapiro to a call to free. Otherwise, the following additional semantics 14340266059SGregory Neil Shapiro apply. 14440266059SGregory Neil Shapiro <p> 14540266059SGregory Neil Shapiro 14640266059SGregory Neil Shapiro If ptr is NULL, this function has no effect. 14740266059SGregory Neil Shapiro <p> 14840266059SGregory Neil Shapiro 14940266059SGregory Neil Shapiro Otherwise, ptr is required to be a value that was 15040266059SGregory Neil Shapiro previously returned by sm_malloc or sm_realloc, and which 15140266059SGregory Neil Shapiro has not yet been freed by sm_free. If this condition is not 15240266059SGregory Neil Shapiro met, then the program is aborted using sm_abort. 15340266059SGregory Neil Shapiro <p> 15440266059SGregory Neil Shapiro 15540266059SGregory Neil Shapiro Otherwise, if there is no error, then the block pointed to by ptr 15640266059SGregory Neil Shapiro will be set to all zeros before free() is called. This is intended 15740266059SGregory Neil Shapiro to assist in detecting the use of dangling pointers. 15840266059SGregory Neil Shapiro</dl> 15940266059SGregory Neil Shapiro 16040266059SGregory Neil Shapiro<h2> How to control tag information </h2> 16140266059SGregory Neil Shapiro 16240266059SGregory Neil ShapiroWhen heap checking is enabled, 16340266059SGregory Neil Shapirothe heap package maintains a hash table which associates the 16440266059SGregory Neil Shapirofollowing values with each currently allocated block: 16540266059SGregory Neil Shapiro 16640266059SGregory Neil Shapiro<dl> 16740266059SGregory Neil Shapiro<dt> 16840266059SGregory Neil Shapiro<tt> size_t size </tt> 16940266059SGregory Neil Shapiro<dd> 17040266059SGregory Neil Shapiro The size of the block. 17140266059SGregory Neil Shapiro<dt> 17240266059SGregory Neil Shapiro<tt> char *tag </tt> 17340266059SGregory Neil Shapiro<dd> 17440266059SGregory Neil Shapiro By default, this is the name of the source file from which 17540266059SGregory Neil Shapiro the block was allocated, but you can specify an arbitrary 17640266059SGregory Neil Shapiro string pointer, or <tt>NULL</tt>. 17740266059SGregory Neil Shapiro<dt> 17840266059SGregory Neil Shapiro<tt> int num </tt> 17940266059SGregory Neil Shapiro<dd> 18040266059SGregory Neil Shapiro By default, this is the line number from which the block was 18140266059SGregory Neil Shapiro allocated. 18240266059SGregory Neil Shapiro<dt> 18340266059SGregory Neil Shapiro<tt> int group </tt> 18440266059SGregory Neil Shapiro<dd> 18540266059SGregory Neil Shapiro By convention, group==0 indicates that the block is permanently 18640266059SGregory Neil Shapiro allocated and will never be freed. The meanings of other group 18740266059SGregory Neil Shapiro numbers are defined by the application developer. 18840266059SGregory Neil Shapiro Unless you take special action, all blocks allocated by 18940266059SGregory Neil Shapiro <tt>sm_malloc</tt> and <tt>sm_malloc_x</tt> will be assigned 19040266059SGregory Neil Shapiro to group 1. 19140266059SGregory Neil Shapiro</dl> 19240266059SGregory Neil Shapiro 19340266059SGregory Neil ShapiroThese tag values are printed by <tt>sm_heap_report</tt>, 19440266059SGregory Neil Shapiroand are used to help analyze memory allocation behaviour 19540266059SGregory Neil Shapiroand to find memory leaks. 19640266059SGregory Neil ShapiroThe following functions give you precise control over the 19740266059SGregory Neil Shapirotag values associated with each allocated block. 19840266059SGregory Neil Shapiro 19940266059SGregory Neil Shapiro<dl> 20040266059SGregory Neil Shapiro<dt> 20140266059SGregory Neil Shapiro<tt> void *sm_malloc_tagged(size_t size, int tag, int num, int group) </tt> 20240266059SGregory Neil Shapiro<dd> 20340266059SGregory Neil Shapiro Just like <tt>sm_malloc</tt>, except you directly specify 20440266059SGregory Neil Shapiro all of the tag values. 20540266059SGregory Neil Shapiro If heap checking is disabled at compile time, then a call 20640266059SGregory Neil Shapiro to <tt>sm_malloc_tagged</tt> is macro expanded to 20740266059SGregory Neil Shapiro a call to <tt>malloc</tt>. 20840266059SGregory Neil Shapiro <p> 20940266059SGregory Neil Shapiro 21040266059SGregory Neil Shapiro Note that the expression <tt>sm_malloc(size)</tt> is macro expanded to 21140266059SGregory Neil Shapiro 21240266059SGregory Neil Shapiro<blockquote><pre> 21340266059SGregory Neil Shapirosm_malloc_tagged(size, __FILE__, __LINE__, sm_heap_group()) 21440266059SGregory Neil Shapiro</pre></blockquote> 21540266059SGregory Neil Shapiro 21640266059SGregory Neil Shapiro<dt> 21740266059SGregory Neil Shapiro<tt> void *sm_malloc_tagged_x(size_t size, int tag, int num, int group) </tt> 21840266059SGregory Neil Shapiro<dd> 21940266059SGregory Neil Shapiro A variant of <tt>sm_malloc_tagged</tt> 22040266059SGregory Neil Shapiro that raises an exception on error. 22140266059SGregory Neil Shapiro A call to <tt>sm_malloc_x</tt> is macro expanded 22240266059SGregory Neil Shapiro to a call to <tt>sm_malloc_tagged_x</tt>. 22340266059SGregory Neil Shapiro <p> 22440266059SGregory Neil Shapiro 22540266059SGregory Neil Shapiro<dt> 22640266059SGregory Neil Shapiro<tt> int sm_heap_group() </tt> 22740266059SGregory Neil Shapiro<dd> 22840266059SGregory Neil Shapiro The heap package maintains a thread-local variable containing 22940266059SGregory Neil Shapiro the current group number. 23040266059SGregory Neil Shapiro This is the group that <tt>sm_malloc</tt> and <tt>sm_malloc_x</tt> 23140266059SGregory Neil Shapiro will assign a newly allocated block to. 23240266059SGregory Neil Shapiro The initial value of this variable is 1. 23340266059SGregory Neil Shapiro The current value of this variable is returned by 23440266059SGregory Neil Shapiro <tt>sm_heap_group()</tt>. 23540266059SGregory Neil Shapiro <p> 23640266059SGregory Neil Shapiro 23740266059SGregory Neil Shapiro<dt> 23840266059SGregory Neil Shapiro<tt> int sm_heap_setgroup(int g) </tt> 23940266059SGregory Neil Shapiro<dd> 24040266059SGregory Neil Shapiro Set the current group to the specified value. 24140266059SGregory Neil Shapiro</dl> 24240266059SGregory Neil Shapiro 24340266059SGregory Neil ShapiroHere are two examples of how you might use these interfaces. 24440266059SGregory Neil Shapiro 24540266059SGregory Neil Shapiro<ol> 24640266059SGregory Neil Shapiro<li> 24740266059SGregory Neil ShapiroOne way to detect memory leaks is to turn on heap checking 24840266059SGregory Neil Shapiroand call <tt>sm_heap_report(stdout,2)</tt> 24940266059SGregory Neil Shapirowhen the program exits. 25040266059SGregory Neil ShapiroThis prints a list of all allocated blocks that do not belong to group 0. 25140266059SGregory Neil Shapiro(Blocks in group 0 are assumed to be permanently allocated, 25240266059SGregory Neil Shapiroand so their existence at program exit does not indicate a leak.) 25340266059SGregory Neil ShapiroIf you want to allocate a block and assign it to group 0, 25440266059SGregory Neil Shapiroyou have two choices: 25540266059SGregory Neil Shapiro 25640266059SGregory Neil Shapiro<blockquote><pre> 25740266059SGregory Neil Shapiroint g = sm_heap_group(); 25840266059SGregory Neil Shapirosm_heap_setgroup(0); 25940266059SGregory Neil Shapirop = sm_malloc_x(size); 26040266059SGregory Neil Shapirosm_heap_setgroup(g); 26140266059SGregory Neil Shapiro</pre></blockquote> 26240266059SGregory Neil Shapiro 26340266059SGregory Neil Shapiroor 26440266059SGregory Neil Shapiro 26540266059SGregory Neil Shapiro<blockquote><pre> 26640266059SGregory Neil Shapirop = sm_malloc_tagged_x(size, __FILE__, __LINE__, 0); 26740266059SGregory Neil Shapiro</pre></blockquote> 26840266059SGregory Neil Shapiro 26940266059SGregory Neil Shapiro<li> 27040266059SGregory Neil ShapiroSuppose you have a utility function foo_alloc which allocates 27140266059SGregory Neil Shapiroand initializes a 'foo' object. When sm_heap_report is called, 27240266059SGregory Neil Shapiroall unfreed 'foo' objects will be reported to have the same 27340266059SGregory Neil Shapirosource code file name and line number. 27440266059SGregory Neil ShapiroThat might make it difficult to determine where a memory leak is. 27540266059SGregory Neil Shapiro<p> 27640266059SGregory Neil Shapiro 27740266059SGregory Neil ShapiroHere is how you can arrange for more precise reporting for 27840266059SGregory Neil Shapirounfreed foo objects: 27940266059SGregory Neil Shapiro 28040266059SGregory Neil Shapiro<blockquote><pre> 28140266059SGregory Neil Shapiro#include <sm/heap.h> 28240266059SGregory Neil Shapiro 28340266059SGregory Neil Shapiro#if SM_HEAP_CHECK 28440266059SGregory Neil Shapiro# define foo_alloc_x() foo_alloc_tagged_x(__FILE__,__LINE) 28540266059SGregory Neil Shapiro FOO *foo_alloc_tagged_x(char *, int); 28640266059SGregory Neil Shapiro#else 28740266059SGregory Neil Shapiro FOO *foo_alloc_x(void); 28840266059SGregory Neil Shapiro# define foo_alloc_tagged_x(file,line) foo_alloc_x() 28940266059SGregory Neil Shapiro#endif 29040266059SGregory Neil Shapiro 29140266059SGregory Neil Shapiro... 29240266059SGregory Neil Shapiro 29340266059SGregory Neil Shapiro#if SM_HEAP_CHECK 29440266059SGregory Neil ShapiroFOO * 29540266059SGregory Neil Shapirofoo_alloc_tagged_x(char *file, int line) 29640266059SGregory Neil Shapiro#else 29740266059SGregory Neil ShapiroFOO * 29840266059SGregory Neil Shapirofoo_alloc_x(void) 29940266059SGregory Neil Shapiro#endif 30040266059SGregory Neil Shapiro{ 30140266059SGregory Neil Shapiro FOO *p; 30240266059SGregory Neil Shapiro 30340266059SGregory Neil Shapiro p = sm_malloc_tagged_x(sizeof(FOO), file, line, sm_heap_group()); 30440266059SGregory Neil Shapiro ... 30540266059SGregory Neil Shapiro return p; 30640266059SGregory Neil Shapiro} 30740266059SGregory Neil Shapiro</pre></blockquote> 30840266059SGregory Neil Shapiro</ol> 30940266059SGregory Neil Shapiro 31040266059SGregory Neil Shapiro<h2> How to dump the block list </h2> 31140266059SGregory Neil Shapiro 31240266059SGregory Neil ShapiroTo perform memory leak detection, you need to arrange for your 31340266059SGregory Neil Shapiroprogram to call sm_heap_report at appropriate times. 31440266059SGregory Neil Shapiro 31540266059SGregory Neil Shapiro<dl> 31640266059SGregory Neil Shapiro<dt> 31740266059SGregory Neil Shapiro<tt> void sm_heap_report(FILE *stream, int verbosity) </tt> 31840266059SGregory Neil Shapiro<dd> 31940266059SGregory Neil Shapiro If heap checking is disabled, this function does nothing. 32040266059SGregory Neil Shapiro If verbosity <= 0, this function does nothing. 32140266059SGregory Neil Shapiro <p> 32240266059SGregory Neil Shapiro 32340266059SGregory Neil Shapiro If verbosity >= 1, then sm_heap_report prints a single line 32440266059SGregory Neil Shapiro to stream giving the total number of bytes currently allocated. 32540266059SGregory Neil Shapiro If you call sm_heap_report each time the program has reached a 32640266059SGregory Neil Shapiro "ground state", and the reported amount of heap storage is 32740266059SGregory Neil Shapiro monotonically increasing, that indicates a leak. 32840266059SGregory Neil Shapiro <p> 32940266059SGregory Neil Shapiro 33040266059SGregory Neil Shapiro If verbosity >= 2, then sm_heap_report additionally prints one line 33140266059SGregory Neil Shapiro for each block of memory currently allocated, providing that 33240266059SGregory Neil Shapiro the group != 0. 33340266059SGregory Neil Shapiro (Such blocks are assumed to be permanently allocated storage, and 33440266059SGregory Neil Shapiro are not reported to cut down the level of noise.) 33540266059SGregory Neil Shapiro <p> 33640266059SGregory Neil Shapiro 33740266059SGregory Neil Shapiro If verbosity >= 3, then sm_heap_report prints one line for each 33840266059SGregory Neil Shapiro allocated block, regardless of the group. 33940266059SGregory Neil Shapiro</dl> 34040266059SGregory Neil Shapiro 34140266059SGregory Neil Shapiro<h2> How to enable heap checking </h2> 34240266059SGregory Neil Shapiro 34340266059SGregory Neil ShapiroThe overhead of using the package can be made as small as you want. 34440266059SGregory Neil ShapiroYou have three options: 34540266059SGregory Neil Shapiro 34640266059SGregory Neil Shapiro<ol> 34740266059SGregory Neil Shapiro<li> 34840266059SGregory Neil Shapiro If you compile your software with -DSM_HEAP_CHECK=0 then 34940266059SGregory Neil Shapiro sm_malloc, sm_realloc and sm_free will be redefined 35040266059SGregory Neil Shapiro as macros that call malloc, realloc, and free. In this case, 35140266059SGregory Neil Shapiro there is zero overhead. 35240266059SGregory Neil Shapiro<li> 35340266059SGregory Neil Shapiro If you do not define -DSM_HEAP_CHECK=0, and you do not explicitly 35440266059SGregory Neil Shapiro turn on heap checking at run time, then your program will run 35540266059SGregory Neil Shapiro without error checking and memory leak detection, and the additional 35640266059SGregory Neil Shapiro cost of calling sm_malloc, sm_realloc and sm_free is a 35740266059SGregory Neil Shapiro function call and test. That overhead is sufficiently low that 35840266059SGregory Neil Shapiro the checking code can be left compiled in a production environment. 35940266059SGregory Neil Shapiro<li> 36040266059SGregory Neil Shapiro If you do not define -DSM_HEAP_CHECK=0, and you explicitly turn on 36140266059SGregory Neil Shapiro heap checking at run time, then the additional cost of calling 36240266059SGregory Neil Shapiro sm_malloc, sm_realloc and sm_free is a hash table lookup. 36340266059SGregory Neil Shapiro</ol> 36440266059SGregory Neil Shapiro 36540266059SGregory Neil Shapiro Here's how to modify your application to use the heap package. 36640266059SGregory Neil Shapiro First, change all calls to malloc, realloc and free to sm_malloc, 36740266059SGregory Neil Shapiro sm_realloc and sm_free. 36840266059SGregory Neil Shapiro Make sure that there is a -d command line option that 36940266059SGregory Neil Shapiro uses the libsm debug package to enable named debug options. 37040266059SGregory Neil Shapiro Add the following code to your program just before it calls exit, 37140266059SGregory Neil Shapiro or register an atexit handler function containing the following code: 37240266059SGregory Neil Shapiro 37340266059SGregory Neil Shapiro<blockquote><pre> 37440266059SGregory Neil Shapiro#if SM_HEAP_CHECK 37540266059SGregory Neil Shapiro /* dump the heap, if we are checking for memory leaks */ 37640266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapCheck, 2)) 37740266059SGregory Neil Shapiro sm_heap_report(stdout, sm_debug_level(&SmHeapCheck) - 1); 37840266059SGregory Neil Shapiro#endif 37940266059SGregory Neil Shapiro</pre></blockquote> 38040266059SGregory Neil Shapiro 38140266059SGregory Neil Shapiro To turn on heap checking, use the command line option "-dsm_check_heap.1". 38240266059SGregory Neil Shapiro This will cause a table of all currently allocated blocks to be 38340266059SGregory Neil Shapiro maintained. The table is used by sm_realloc and sm_free to perform 38440266059SGregory Neil Shapiro validity checking on the first argument. 38540266059SGregory Neil Shapiro 38640266059SGregory Neil Shapiro <p> 38740266059SGregory Neil Shapiro The command line option "-dsm_check_heap.2" will cause your application 38840266059SGregory Neil Shapiro to invoke sm_heap_report with verbosity=1 just before exit. 38940266059SGregory Neil Shapiro That will print a single line reporting total storage allocation. 39040266059SGregory Neil Shapiro 39140266059SGregory Neil Shapiro <p> 39240266059SGregory Neil Shapiro The command line option "-dsm_check_heap.3" will cause your application 39340266059SGregory Neil Shapiro to invoke sm_heap_report with verbosity=2 just before exit. 39440266059SGregory Neil Shapiro This will print a list of all leaked blocks. 39540266059SGregory Neil Shapiro 39640266059SGregory Neil Shapiro <p> 39740266059SGregory Neil Shapiro The command line option "-dsm_check_heap.4" will cause your application 39840266059SGregory Neil Shapiro to invoke sm_heap_report with verbosity=3 just before exit. 39940266059SGregory Neil Shapiro This will print a list of all allocated blocks. 40040266059SGregory Neil Shapiro 40140266059SGregory Neil Shapiro<h2> Using sm_heap_register </h2> 40240266059SGregory Neil Shapiro 40340266059SGregory Neil Shapiro Suppose you call a library routine foo that allocates a block of storage 40440266059SGregory Neil Shapiro for you using malloc, and expects you to free the block later using 40540266059SGregory Neil Shapiro free. Because the storage was not allocated using sm_malloc, you 40640266059SGregory Neil Shapiro will normally get an abort if you try to pass the pointer to 40740266059SGregory Neil Shapiro sm_free. The way to fix this problem is to 'register' the pointer 40840266059SGregory Neil Shapiro returned by foo with the heap package, by calling sm_heap_register: 40940266059SGregory Neil Shapiro 41040266059SGregory Neil Shapiro<blockquote><pre> 41140266059SGregory Neil Shapirobool sm_heap_register(ptr, size, file, line, group) 41240266059SGregory Neil Shapiro</pre></blockquote> 41340266059SGregory Neil Shapiro 41440266059SGregory Neil Shapiro The 'ptr' argument is the pointer returned by foo. The 'size' argument 41540266059SGregory Neil Shapiro can be smaller than the actual size of the allocated block, but it must 41640266059SGregory Neil Shapiro not be larger. The file and line arguments indicate at which line of 41740266059SGregory Neil Shapiro source code the block was allocated, and is printed by sm_heap_report. 41840266059SGregory Neil Shapiro For group, you probably want to pass sm_heap_group(). 41940266059SGregory Neil Shapiro <p> 42040266059SGregory Neil Shapiro This function returns <tt>true</tt> on success, 42140266059SGregory Neil Shapiro or <tt>false</tt> if it failed due to heap exhaustion. 42240266059SGregory Neil Shapiro 42340266059SGregory Neil Shapiro</body> 42440266059SGregory Neil Shapiro</html> 425