NASD provides its own interfaces for memory allocation and deallocation. These
should be used in preference to platform-provided interfaces (such as
malloc()
and free()
) to provide greater portability,
readability, and debugability to code. The NASD memory interface includes
mechanisms for detecting and identifying core leaks as well as limited
bounds-checking (fenceposting).
To use the NASD memory interface, a file must include <nasd/nasd_mem.h>
.
To initialize the memory module, call nasd_mem_init()
. Like most
module initialization functions, this requires no arguments. When the module is
no longer needed, call nasd_mem_shutdown()
. Note that the
interface should be shut down only after freeing allocated memory.
In addition to module initialization and shutdown, the memory module provides
two key entrypoints:
NASD_Malloc()
assigns to pointer
a valid pointer to size
bytes of memory, using cast
as a typecast for this assignment.
To release memory acquired from a call to NASD_Malloc()
, one calls
NASD_Free()
with the first argument being pointer
as returned by NASD_Malloc()
, and
the second argument being the number of bytes to free (identical to size
as passed to NASD_Malloc()
). The results of calling NASD_Free()
with a size
that does not correspond to the size used to allocate
that region of memory or calling NASD_Free()
with a pointer that
did not result from a call to NASD_Malloc()
is undefined.
For instance, to allocate two kilobytes of memory, and later free it, one might use:
NASD_MEM_COUNT_ALLOC
is defined nonzero in nasd_options.h
,
the memory module will provide the global symbol nasd_mem_allocated
of
type nasd_int64
. This variable will, at any time, report the amount of
memory currently "outstanding"; that is, memory allocated with
NASD_Malloc()
but not yet deallocated
with NASD_Free()
. It is not permissible to write this value. It is
permissible to read it after calling nasd_mem_shutdown()
. This value
may be used as an indication of whether or not there is a core leak in the system.
After all modules have been shut down, this value should be zero. If it is nonzero,
something leaked from the core.
Of course, knowing that a core leak has occurred and knowing where it
occurred are two different matters. While pinpointing the moment at which
the reference to leaked memory was lost or identifying memory as simply
allocated but never freed is beyond the scope of the memory module, it can
identify where unfreed ranges of memory were allocated. When
NASD_TRACK_ALLOCATIONS
is defined nonzero in nasd_options.h
,
the memory module will remember the file and line number of each call to
NASD_Malloc()
for outstanding
memory ranges, and can report this information. If NASD_TRACK_ALLOCATIONS
is enabled, this will be done automatically when nasd_mem_shutdown()
is called for the last time (that is, when the reference count on the memory module
zeroes). This dump can also be triggered by calling nasd_mem_dump_unfreed()
,
which takes no arguments and returns nasd_status_t
. Additionally, when
NASD_TRACK_ALLOCATIONS
is enabled, the memory subsystem will generate
a warning any time NASD_Free()
is called with a different size than
resulted from the corresponding call to NASD_Malloc()
,
as well as warnings for calls to NASD_Free()
with pointers that did
not result from calls to NASD_Malloc()
.
Be aware that enabling NASD_TRACK_ALLOCATIONS
causes both memory usage
and the expense of memory operations to become inflated. It is recommended that this
mode only be enabled when it is necessary to track down a particular bug.
One common mistake when programming is writing past the beginning or end of
a chunk of allocated memory. If NASD_MEM_FENCEPOST
is defined
to a value greater than or equal to three, NASD_MEM_FENCEPOST
unsigned long
s will be prepended and appended to each buffer of
allocated memory, and initialized with well-known garbage values
(NASD_MEM_FENCEPOST_PATTERN
). When the memory is freed, the
memory module will determine if these values have been altered, and generate
warnings if needed. Like NASD_TRACK_ALLOCATIONS
, this operation causes
both memory usage and the expense of memory operations to become inflated. It
is therefore recommended that NASD_MEM_FENCEPOST
only be enabled
when necessary.
Uninitialized memory is the bane of many programmers, partly because
it involves a degree of nondeterminism when attempting to reproduce bugs.
The memory module can assist in identifying uninitialized memory by filling
buffers resulting from calls to NASD_Malloc()
with a well-known
fill pattern. If NASD_MEM_FILL
is defined nonzero in
nasd_options.h
, then the value it is defined to will be used as
a 32-bit fill pattern for freshly-allocated memory. A popular value to set
this to is 0xdeadbeef
, because that places recognizable nonzero
bits in all 32 positions, and this is not a valid pointer on most platforms.
![]() | ![]() | ![]() |
---|---|---|
Thread groups | Freelists | NASD Programmer's Documentation |