Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / libsm / heap.html
blobbc32b012e7570fb8a58002c06e9570c9d0e648e1
1 <html>
2 <head>
3 <title>libsm : Memory Allocation</title>
4 </head>
5 <body>
7 <a href="index.html">Back to libsm overview</a>
9 <center>
10 <h1> libsm : Memory Allocation </h1>
11 <br> $Id: heap.html,v 1.9 2000/12/08 21:41:42 ca Exp $
12 </center>
14 <h2> Introduction </h2>
16 The heap package provides a layer of abstraction on top of
17 <tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt>
18 that provides optional error checking and memory leak detection,
19 and which optionally raises an exception when an allocation request
20 cannot be satisfied.
22 <h2> Synopsis </h2>
24 <pre>
25 #include &lt;sm/heap.h&gt;
28 ** Wrappers for malloc, realloc, free
30 void *sm_malloc(size_t size);
31 void *sm_realloc(void *ptr, size_t size);
32 void sm_free(void *ptr);
35 ** Wrappers for malloc, realloc that raise an exception instead of
36 ** returning NULL on heap exhaustion.
38 void *sm_malloc_x(size_t size);
39 void *sm_realloc_x(void *ptr, size_t size);
42 ** Print a list of currently allocated blocks,
43 ** used to diagnose memory leaks.
45 void sm_heap_report(FILE *stream, int verbosity);
48 ** Low level interfaces.
50 int sm_heap_group();
51 int sm_heap_setgroup(int g);
52 int sm_heap_newgroup();
53 void *sm_malloc_tagged(size_t size, char *file, int line, int group);
54 void *sm_malloc_tagged_x(size_t size, char *file, int line, int group);
55 bool sm_heap_register(void *ptr, size_t size, char *file, int line);
56 </pre>
58 <h2> How to allocate and free memory </h2>
60 <tt>sm_malloc</tt>, <tt>sm_realloc</tt> and <tt>sm_free</tt>
61 are portable plug in replacements
62 for <tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt> that provide
63 error checking and memory leak detection.
64 <tt>sm_malloc_x</tt> and <tt>sm_realloc_x</tt>
65 are variants of
66 <tt>sm_malloc</tt> and <tt>sm_realloc</tt>
67 that raise an exception on error.
68 To use the package effectively,
69 all calls to <tt>malloc</tt>, <tt>realloc</tt> and <tt>free</tt>
70 should be replaced by calls
71 to the corresponding <tt>sm_</tt>* routines.
73 <dl>
74 <dt>
75 <tt> void *sm_malloc(size_t size) </tt>
76 <dd>
77 This function is a plug-in replacement for <tt>malloc</tt>.
78 It allocates <tt>size</tt> bytes of memory on the heap
79 and returns a pointer to it,
80 or it returns <tt>NULL</tt> on failure.
81 <p>
83 The C standard says that <tt>malloc(0)</tt> may return
84 either <tt>NULL</tt> or a non-<tt>NULL</tt> value.
85 To ensure consistent behaviour on all platforms,
86 <tt>sm_malloc(0)</tt> is equivalent to <tt>sm_malloc(1)</tt>.
87 <p>
89 In addition, if heap checking is enabled, then <tt>sm_malloc</tt>
90 maintains a hash table describing all currently allocated
91 memory blocks. This table is used for argument validity
92 checking in <tt>sm_realloc</tt> and <tt>sm_free</tt>,
93 and it can be printed using <tt>sm_heap_report</tt>
94 as an aid to finding memory leaks.
95 <p>
97 <dt>
98 <tt> void *sm_malloc_x(size_t size) </tt>
99 <dd>
100 This function is just like <tt>sm_malloc</tt>
101 except that it raises the <tt>SmHeapOutOfMemory</tt> exception
102 instead of returning <tt>NULL</tt> on error.
105 <dt>
106 <tt> void *sm_realloc(void *ptr, size_t size) </tt>
107 <dd>
108 This function is a plug-in replacement for <tt>realloc</tt>.
109 If <tt>ptr</tt> is null then this call is equivalent
110 to <tt>sm_malloc(size)</tt>.
111 Otherwise, the size of the object pointed to by <tt>ptr</tt>
112 is changed to <tt>size</tt> bytes, and a pointer to the
113 (possibly moved) object is returned.
114 If the space cannot be allocated, then the object pointed to
115 by <tt>ptr</tt> is unchanged and <tt>NULL</tt> is returned.
118 If <tt>size</tt> is 0 then we pretend that <tt>size</tt> is 1.
119 This may be a mistake.
122 If ptr is not NULL and heap checking is enabled,
123 then ptr is required to be a value that was
124 previously returned by sm_malloc or sm_realloc, and which
125 has not yet been freed by sm_free. If this condition is not
126 met, then the program is aborted using sm_abort.
129 <dt>
130 <tt> void *sm_realloc_x(void *ptr, size_t size) </tt>
131 <dd>
132 This function is just like <tt>sm_realloc</tt>
133 except that it raises the SmHeapOutOfMemory exception
134 instead of returning <tt>NULL</tt> on error.
137 <dt>
138 <tt> void sm_free(void *ptr) </tt>
139 <dd>
140 This function is a plug-in replacement for free.
141 If heap checking is disabled, then this function is equivalent
142 to a call to free. Otherwise, the following additional semantics
143 apply.
146 If ptr is NULL, this function has no effect.
149 Otherwise, ptr is required to be a value that was
150 previously returned by sm_malloc or sm_realloc, and which
151 has not yet been freed by sm_free. If this condition is not
152 met, then the program is aborted using sm_abort.
155 Otherwise, if there is no error, then the block pointed to by ptr
156 will be set to all zeros before free() is called. This is intended
157 to assist in detecting the use of dangling pointers.
158 </dl>
160 <h2> How to control tag information </h2>
162 When heap checking is enabled,
163 the heap package maintains a hash table which associates the
164 following values with each currently allocated block:
166 <dl>
167 <dt>
168 <tt> size_t size </tt>
169 <dd>
170 The size of the block.
171 <dt>
172 <tt> char *tag </tt>
173 <dd>
174 By default, this is the name of the source file from which
175 the block was allocated, but you can specify an arbitrary
176 string pointer, or <tt>NULL</tt>.
177 <dt>
178 <tt> int num </tt>
179 <dd>
180 By default, this is the line number from which the block was
181 allocated.
182 <dt>
183 <tt> int group </tt>
184 <dd>
185 By convention, group==0 indicates that the block is permanently
186 allocated and will never be freed. The meanings of other group
187 numbers are defined by the application developer.
188 Unless you take special action, all blocks allocated by
189 <tt>sm_malloc</tt> and <tt>sm_malloc_x</tt> will be assigned
190 to group 1.
191 </dl>
193 These tag values are printed by <tt>sm_heap_report</tt>,
194 and are used to help analyze memory allocation behaviour
195 and to find memory leaks.
196 The following functions give you precise control over the
197 tag values associated with each allocated block.
199 <dl>
200 <dt>
201 <tt> void *sm_malloc_tagged(size_t size, int tag, int num, int group) </tt>
202 <dd>
203 Just like <tt>sm_malloc</tt>, except you directly specify
204 all of the tag values.
205 If heap checking is disabled at compile time, then a call
206 to <tt>sm_malloc_tagged</tt> is macro expanded to
207 a call to <tt>malloc</tt>.
210 Note that the expression <tt>sm_malloc(size)</tt> is macro expanded to
212 <blockquote><pre>
213 sm_malloc_tagged(size, __FILE__, __LINE__, sm_heap_group())
214 </pre></blockquote>
216 <dt>
217 <tt> void *sm_malloc_tagged_x(size_t size, int tag, int num, int group) </tt>
218 <dd>
219 A variant of <tt>sm_malloc_tagged</tt>
220 that raises an exception on error.
221 A call to <tt>sm_malloc_x</tt> is macro expanded
222 to a call to <tt>sm_malloc_tagged_x</tt>.
225 <dt>
226 <tt> int sm_heap_group() </tt>
227 <dd>
228 The heap package maintains a thread-local variable containing
229 the current group number.
230 This is the group that <tt>sm_malloc</tt> and <tt>sm_malloc_x</tt>
231 will assign a newly allocated block to.
232 The initial value of this variable is 1.
233 The current value of this variable is returned by
234 <tt>sm_heap_group()</tt>.
237 <dt>
238 <tt> int sm_heap_setgroup(int g) </tt>
239 <dd>
240 Set the current group to the specified value.
241 </dl>
243 Here are two examples of how you might use these interfaces.
245 <ol>
246 <li>
247 One way to detect memory leaks is to turn on heap checking
248 and call <tt>sm_heap_report(stdout,2)</tt>
249 when the program exits.
250 This prints a list of all allocated blocks that do not belong to group 0.
251 (Blocks in group 0 are assumed to be permanently allocated,
252 and so their existence at program exit does not indicate a leak.)
253 If you want to allocate a block and assign it to group 0,
254 you have two choices:
256 <blockquote><pre>
257 int g = sm_heap_group();
258 sm_heap_setgroup(0);
259 p = sm_malloc_x(size);
260 sm_heap_setgroup(g);
261 </pre></blockquote>
265 <blockquote><pre>
266 p = sm_malloc_tagged_x(size, __FILE__, __LINE__, 0);
267 </pre></blockquote>
269 <li>
270 Suppose you have a utility function foo_alloc which allocates
271 and initializes a 'foo' object. When sm_heap_report is called,
272 all unfreed 'foo' objects will be reported to have the same
273 source code file name and line number.
274 That might make it difficult to determine where a memory leak is.
277 Here is how you can arrange for more precise reporting for
278 unfreed foo objects:
280 <blockquote><pre>
281 #include &lt;sm/heap.h&gt;
283 #if SM_HEAP_CHECK
284 # define foo_alloc_x() foo_alloc_tagged_x(__FILE__,__LINE)
285 FOO *foo_alloc_tagged_x(char *, int);
286 #else
287 FOO *foo_alloc_x(void);
288 # define foo_alloc_tagged_x(file,line) foo_alloc_x()
289 #endif
293 #if SM_HEAP_CHECK
294 FOO *
295 foo_alloc_tagged_x(char *file, int line)
296 #else
297 FOO *
298 foo_alloc_x(void)
299 #endif
301 FOO *p;
303 p = sm_malloc_tagged_x(sizeof(FOO), file, line, sm_heap_group());
305 return p;
307 </pre></blockquote>
308 </ol>
310 <h2> How to dump the block list </h2>
312 To perform memory leak detection, you need to arrange for your
313 program to call sm_heap_report at appropriate times.
315 <dl>
316 <dt>
317 <tt> void sm_heap_report(FILE *stream, int verbosity) </tt>
318 <dd>
319 If heap checking is disabled, this function does nothing.
320 If verbosity &lt;= 0, this function does nothing.
323 If verbosity &gt;= 1, then sm_heap_report prints a single line
324 to stream giving the total number of bytes currently allocated.
325 If you call sm_heap_report each time the program has reached a
326 "ground state", and the reported amount of heap storage is
327 monotonically increasing, that indicates a leak.
330 If verbosity &gt;= 2, then sm_heap_report additionally prints one line
331 for each block of memory currently allocated, providing that
332 the group != 0.
333 (Such blocks are assumed to be permanently allocated storage, and
334 are not reported to cut down the level of noise.)
337 If verbosity &gt;= 3, then sm_heap_report prints one line for each
338 allocated block, regardless of the group.
339 </dl>
341 <h2> How to enable heap checking </h2>
343 The overhead of using the package can be made as small as you want.
344 You have three options:
346 <ol>
347 <li>
348 If you compile your software with -DSM_HEAP_CHECK=0 then
349 sm_malloc, sm_realloc and sm_free will be redefined
350 as macros that call malloc, realloc, and free. In this case,
351 there is zero overhead.
352 <li>
353 If you do not define -DSM_HEAP_CHECK=0, and you do not explicitly
354 turn on heap checking at run time, then your program will run
355 without error checking and memory leak detection, and the additional
356 cost of calling sm_malloc, sm_realloc and sm_free is a
357 function call and test. That overhead is sufficiently low that
358 the checking code can be left compiled in a production environment.
359 <li>
360 If you do not define -DSM_HEAP_CHECK=0, and you explicitly turn on
361 heap checking at run time, then the additional cost of calling
362 sm_malloc, sm_realloc and sm_free is a hash table lookup.
363 </ol>
365 Here's how to modify your application to use the heap package.
366 First, change all calls to malloc, realloc and free to sm_malloc,
367 sm_realloc and sm_free.
368 Make sure that there is a -d command line option that
369 uses the libsm debug package to enable named debug options.
370 Add the following code to your program just before it calls exit,
371 or register an atexit handler function containing the following code:
373 <blockquote><pre>
374 #if SM_HEAP_CHECK
375 /* dump the heap, if we are checking for memory leaks */
376 if (sm_debug_active(&SmHeapCheck, 2))
377 sm_heap_report(stdout, sm_debug_level(&SmHeapCheck) - 1);
378 #endif
379 </pre></blockquote>
381 To turn on heap checking, use the command line option "-dsm_check_heap.1".
382 This will cause a table of all currently allocated blocks to be
383 maintained. The table is used by sm_realloc and sm_free to perform
384 validity checking on the first argument.
387 The command line option "-dsm_check_heap.2" will cause your application
388 to invoke sm_heap_report with verbosity=1 just before exit.
389 That will print a single line reporting total storage allocation.
392 The command line option "-dsm_check_heap.3" will cause your application
393 to invoke sm_heap_report with verbosity=2 just before exit.
394 This will print a list of all leaked blocks.
397 The command line option "-dsm_check_heap.4" will cause your application
398 to invoke sm_heap_report with verbosity=3 just before exit.
399 This will print a list of all allocated blocks.
401 <h2> Using sm_heap_register </h2>
403 Suppose you call a library routine foo that allocates a block of storage
404 for you using malloc, and expects you to free the block later using
405 free. Because the storage was not allocated using sm_malloc, you
406 will normally get an abort if you try to pass the pointer to
407 sm_free. The way to fix this problem is to 'register' the pointer
408 returned by foo with the heap package, by calling sm_heap_register:
410 <blockquote><pre>
411 bool sm_heap_register(ptr, size, file, line, group)
412 </pre></blockquote>
414 The 'ptr' argument is the pointer returned by foo. The 'size' argument
415 can be smaller than the actual size of the allocated block, but it must
416 not be larger. The file and line arguments indicate at which line of
417 source code the block was allocated, and is printed by sm_heap_report.
418 For group, you probably want to pass sm_heap_group().
420 This function returns <tt>true</tt> on success,
421 or <tt>false</tt> if it failed due to heap exhaustion.
423 </body>
424 </html>