Back to libsm overviewlibsm : Memory Allocation
$Id: heap.html,v 1.9 2000/12/08 21:41:42 ca Exp $Introduction
The heap package provides a layer of abstraction on top of malloc, realloc and free that provides optional error checking and memory leak detection, and which optionally raises an exception when an allocation request cannot be satisfied.Synopsis
#include <sm/heap.h> /* ** Wrappers for malloc, realloc, free */ void *sm_malloc(size_t size); void *sm_realloc(void *ptr, size_t size); void sm_free(void *ptr); /* ** Wrappers for malloc, realloc that raise an exception instead of ** returning NULL on heap exhaustion. */ void *sm_malloc_x(size_t size); void *sm_realloc_x(void *ptr, size_t size); /* ** Print a list of currently allocated blocks, ** used to diagnose memory leaks. */ void sm_heap_report(FILE *stream, int verbosity); /* ** Low level interfaces. */ int sm_heap_group(); int sm_heap_setgroup(int g); int sm_heap_newgroup(); void *sm_malloc_tagged(size_t size, char *file, int line, int group); void *sm_malloc_tagged_x(size_t size, char *file, int line, int group); bool sm_heap_register(void *ptr, size_t size, char *file, int line);How to allocate and free memory
sm_malloc, sm_realloc and sm_free are portable plug in replacements for malloc, realloc and free that provide error checking and memory leak detection. sm_malloc_x and sm_realloc_x are variants of sm_malloc and sm_realloc that raise an exception on error. To use the package effectively, all calls to malloc, realloc and free should be replaced by calls to the corresponding sm_* routines.
The C standard says that malloc(0) may return either NULL or a non-NULL value. To ensure consistent behaviour on all platforms, sm_malloc(0) is equivalent to sm_malloc(1).
In addition, if heap checking is enabled, then sm_malloc maintains a hash table describing all currently allocated memory blocks. This table is used for argument validity checking in sm_realloc and sm_free, and it can be printed using sm_heap_report as an aid to finding memory leaks.
If size is 0 then we pretend that size is 1. This may be a mistake.
If ptr is not NULL and heap checking is enabled, then ptr is required to be a value that was previously returned by sm_malloc or sm_realloc, and which has not yet been freed by sm_free. If this condition is not met, then the program is aborted using sm_abort.
If ptr is NULL, this function has no effect.
Otherwise, ptr is required to be a value that was previously returned by sm_malloc or sm_realloc, and which has not yet been freed by sm_free. If this condition is not met, then the program is aborted using sm_abort.
Otherwise, if there is no error, then the block pointed to by ptr will be set to all zeros before free() is called. This is intended to assist in detecting the use of dangling pointers.
Note that the expression sm_malloc(size) is macro expanded to
sm_malloc_tagged(size, __FILE__, __LINE__, sm_heap_group())
orint g = sm_heap_group(); sm_heap_setgroup(0); p = sm_malloc_x(size); sm_heap_setgroup(g);
p = sm_malloc_tagged_x(size, __FILE__, __LINE__, 0);
Here is how you can arrange for more precise reporting for unfreed foo objects:
#include <sm/heap.h>
#if SM_HEAP_CHECK
# define foo_alloc_x() foo_alloc_tagged_x(__FILE__,__LINE)
FOO *foo_alloc_tagged_x(char *, int);
#else
FOO *foo_alloc_x(void);
# define foo_alloc_tagged_x(file,line) foo_alloc_x()
#endif
...
#if SM_HEAP_CHECK
FOO *
foo_alloc_tagged_x(char *file, int line)
#else
FOO *
foo_alloc_x(void)
#endif
{
FOO *p;
p = sm_malloc_tagged_x(sizeof(FOO), file, line, sm_heap_group());
...
return p;
}
If verbosity >= 1, then sm_heap_report prints a single line to stream giving the total number of bytes currently allocated. If you call sm_heap_report each time the program has reached a "ground state", and the reported amount of heap storage is monotonically increasing, that indicates a leak.
If verbosity >= 2, then sm_heap_report additionally prints one line for each block of memory currently allocated, providing that the group != 0. (Such blocks are assumed to be permanently allocated storage, and are not reported to cut down the level of noise.)
If verbosity >= 3, then sm_heap_report prints one line for each allocated block, regardless of the group.
To turn on heap checking, use the command line option "-dsm_check_heap.1". This will cause a table of all currently allocated blocks to be maintained. The table is used by sm_realloc and sm_free to perform validity checking on the first argument.#if SM_HEAP_CHECK /* dump the heap, if we are checking for memory leaks */ if (sm_debug_active(&SmHeapCheck, 2)) sm_heap_report(stdout, sm_debug_level(&SmHeapCheck) - 1); #endif
The command line option "-dsm_check_heap.2" will cause your application to invoke sm_heap_report with verbosity=1 just before exit. That will print a single line reporting total storage allocation.
The command line option "-dsm_check_heap.3" will cause your application to invoke sm_heap_report with verbosity=2 just before exit. This will print a list of all leaked blocks.
The command line option "-dsm_check_heap.4" will cause your application to invoke sm_heap_report with verbosity=3 just before exit. This will print a list of all allocated blocks.
The 'ptr' argument is the pointer returned by foo. The 'size' argument can be smaller than the actual size of the allocated block, but it must not be larger. The file and line arguments indicate at which line of source code the block was allocated, and is printed by sm_heap_report. For group, you probably want to pass sm_heap_group().bool sm_heap_register(ptr, size, file, line, group)
This function returns true on success,
or false if it failed due to heap exhaustion.