SMARTALLOC Details
When you include “smartall.h” and define SMARTALLOC, the following standard system library functions are redefined with the #define mechanism to call corresponding functions within smartall.c instead. (For details of the redefinitions, please refer to smartall.h.)
void *malloc(size_t size)
void *calloc(size_t nelem, size_t elsize)
void *realloc(void *ptr, size_t size)
void free(void *ptr)
void cfree(void *ptr)
cfree()
is a historical artifact identical to free()
.
In addition to allocating storage in the same way as the standard
library functions, the SMARTALLOC versions expand the buffers they
allocate to include information that identifies where each buffer was
allocated and to chain all allocated buffers together. When a buffer is
released, it is removed from the allocated buffer chain. A call on
sm_dump()
is able, by scanning the chain of allocated buffers, to
find all orphaned buffers. Buffers allocated while sm_static(1)
is
in effect are specially flagged so that, despite appearing on the
allocated buffer chain, sm_dump()
will not deem them orphans.
When a buffer is allocated by malloc()
or expanded with
realloc()
, all bytes of newly allocated storage are set to the
hexadecimal value 0x55 (alternating one and zero bits). Note that for
realloc()
this applies only to the bytes added at the end of buffer;
the original contents of the buffer are not modified. Initializing
allocated storage to a distinctive nonzero pattern is intended to catch
code that erroneously assumes newly allocated buffers are cleared to
zero; in fact their contents are random. The calloc()
function,
defined as returning a buffer cleared to zero, continues to zero its
buffers under SMARTALLOC.
Buffers obtained with the SMARTALLOC functions contain a special
sentinel byte at the end of the user data area. This byte is set to a
special key value based upon the buffer’s memory address. When the
buffer is released, the key is tested and if it has been overwritten an
assertion in the free
function will fail. This catches incorrect
program code that stores beyond the storage allocated for the buffer. At
free()
time the queue links are also validated and an assertion
failure will occur if the program has destroyed them by storing before
the start of the allocated storage.
In addition, when a buffer is released with free()
, its contents are
immediately destroyed by overwriting them with the hexadecimal pattern
0xAA (alternating bits, the one’s complement of the initial value
pattern). This will usually trip up code that keeps a pointer to a
buffer that’s been freed and later attempts to reference data within the
released buffer. Incredibly, this is legal in the standard Unix memory
allocation package, which permits programs to free() buffers, then raise
them from the grave with realloc()
. Such program “logic” should be
fixed, not accommodated, and SMARTALLOC brooks no such Lazarus buffer“
nonsense.
Some C libraries allow a zero size argument in calls to malloc()
.
Since this is far more likely to indicate a program error than a
defensible programming stratagem, SMARTALLOC disallows it with an
assertion.
When the standard library realloc()
function is called to expand a
buffer, it attempts to expand the buffer in place if possible, moving it
only if necessary. Because SMARTALLOC must place its own private storage
in the buffer and also to aid in error detection, its version of
realloc()
always moves and copies the buffer except in the trivial
case where the size of the buffer is not being changed. By forcing the
buffer to move on every call and destroying the contents of the old
buffer when it is released, SMARTALLOC traps programs which keep
pointers into a buffer across a call on realloc()
which may move it.
This strategy may prove very costly to programs which make extensive use
of realloc()
. If this proves to be a problem, such programs may wish
to use actuallymalloc()
, actuallyrealloc()
, and
actuallyfree()
for such frequently-adjusted buffers, trading error
detection for performance. Although not specified in the System V
Interface Definition, many C library implementations of realloc()
permit an old buffer argument of NULL, causing realloc()
to allocate
a new buffer. The SMARTALLOC version permits this.
See also
Possible Next Steps
Go back to Smart Memory Allocation.
Go back to Developer Guide.