xref: /freebsd/contrib/sendmail/libsm/heap.html (revision ee7b0571c2c18bdec848ed2044223cc88db29bd8)
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 &lt;sm/heap.h&gt;
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 &lt;sm/heap.h&gt;
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 &lt;= 0, this function does nothing.
32140266059SGregory Neil Shapiro	<p>
32240266059SGregory Neil Shapiro
32340266059SGregory Neil Shapiro	If verbosity &gt;= 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 &gt;= 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 &gt;= 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