Chapter 4
Reference

This chapter provides details for each function in the SmartHeap library. Section 4.1 lists functions by category. Section 4.2 includes a detailed description and syntax of each SmartHeap function. Section 4.3 lists SmartHeap error codes and their meanings.

4.1 Functions by category

4.1.1 Task registration

4.1.2 Memory pools

4.1.3 ANSI standard C API

4.1.4 C++ API

4.1.5 Pointer-based API

4.1.6 Fixed-size API

4.1.7 Handle-based API

4.1.8 Error handling

4.1.9 Debugging

4.2 Function reference (alphabetical)

4.3 Error codes

4.1 Functions by category

This section lists SmartHeap functions by category and briefly describes their purpose. For a complete description of the syntax and use of each function, see §4.2.

4.1.1 Task registration

MemRegisterTask

Initializes the SmartHeap library.

MemUnregisterTask

Terminates the SmartHeap library.

SmartHeap automatically initializes itself on the first call to the library. Alternatively, you can explicitly initialize SmartHeap by calling MemRegisterTask.

MemUnregisterTask terminates SmartHeap, releasing all memory pools and internal data structures to the operating system. SmartHeap maintains a registration reference count, so MemUnregisterTask terminates SmartHeap only when it has been called as many times as MemRegisterTask has been called.

Important! In multi-threaded versions of SmartHeap, MemRegisterTask is required. If your application uses SmartHeap in multiple threads, the first thread must call MemRegisterTask before secondary threads make any SmartHeap calls. This requirement allows SmartHeap to complete initialization of synchronization objects before they’re used.

MemVersion

Returns the SmartHeap version number.

MemProcessSetGrowIncrement

Controls how much memory SmartHeap requests from the operating system when a memory pool needs to grow.

MemProcessSetFreeBytes

Controls how much free space SmartHeap maintains in the large block heap.

MemProcessSetLargeBlockThreshold

Controls the block size SmartHeap manages in its large block heap.

4.1.2 Memory pools

MemPoolAttachShared

Maps a shared memory pool into the current process.

MemPoolInit

Allocates and initializes a memory pool.

MemPoolInitFS

Allocates and initializes a memory pool, and pre-allocates specified count of fixed-size blocks.

MemPoolInitNamedShared

Allocates and initializes a memory pool that can be shared between processes.

MemPoolInitNamedSharedEx

Allocates and initializes a memory pool that can be shared between processes, with specified address and security attributes.

MemPoolInitRegion

Allocates and initializes a memory pool within a user-specified region of memory.

MemPoolFree

Returns all memory in a memory pool to the operating system in one fast operation.

MemPoolSetPageSize

Establishes the size of pages within which SmartHeap sub-allocates.

MemPoolSetBlockSizeFS

Establishes the size of blocks allocated from the pool with MemAllocFS.

MemPoolSetSmallBlockAllocator

Establishes or changes the small-block allocator algorithm for a given memory pool.

MemPoolSetSmallBlockSize

Establishes or changes the threshold below which allocation requests are routed to the small-block memory manager — allows small blocks to be allocated very quickly.

MemPoolSetFloor

Establishes or changes the minimum size to which SmartHeap will ever shrink the pool.

MemPoolSetCeiling

Establishes or changes the maximum size of a memory pool — SmartHeap won’t allow the pool to consume more system memory than the ceiling.

MemPoolPreAllocate

Reserves the specified number of bytes for future allocations from the memory pool.

MemPoolPreAllocateHandles

Reserves handle table entries for use with the handle-based allocation API.

MemPoolSetFreeBytes

Controls free space in a pool just as MemProcessSetFreeBytes controls free space in the large block heap.

MemPoolShrink

Reduces the size of a memory pool, returning memory not currently in use to the operating system.

MemPoolCount

Returns the net count of allocations from a memory pool.

MemPoolSize

Returns the total number of bytes of memory allocated within a memory pool.

MemPoolInfo

Obtains information about a memory pool.

MemPoolFirst

Begins enumeration of all SmartHeap memory pools.

MemPoolNext

Continues enumeration of all SmartHeap memory pools.

MemPoolCheck

Checks each entry in a memory pool for consistency.

MemPoolWalk

Traverses a memory pool, returning information about each entry in turn.

MemPoolSetSerialization

Toggles serialization.

Multi-threading MemPoolLock

Locks a pool for exclusive access by the calling thread.

Multi-threading MemPoolSetMaxSubpools

Controls how many sub-pools SmartHeap will create to avoid heap contention.

Multi-threading MemPoolUnlock

Unlocks a pool, relinquishing exclusive access by the calling thread.

Multi-threading MemPoolSetHighThreads

Sets space/contention tradeoff for a memory pool.

SmartHeap memory pools provide a mechanism for working with a set of related allocations. They establish a working set, occupying a minimal number of pages to satisfy the requested allocations. Related allocations thus tend to be swapped in or out of physical memory together, making memory accesses more efficient.

An entire memory pool can be freed in one operation, which eliminates the need to free each allocated block individually. Memory pools simplify your code and greatly reduce the incidence of common memory errors, such as double freeing or leakage (failing to free memory no longer in use). For example, you could allocate each element of a linked list from a memory pool and free the entire list by simply freeing the memory pool (you can free an individual element if you want to delete that element only).

Memory pools are implemented in SmartHeap by sub-allocation within pages that are a multiple of the system page size (see MemPoolSetPageSize). Each memory pool can contain both fixed- and variable-size blocks. In addition, each pool has a “small block threshold.” SmartHeap automatically routes blocks smaller than the pool’s small block threshold (see MemPoolSetSmallBlockSize) to the fixed-size allocator and routes larger blocks to the general purpose variable-size allocator.

If you use only ANSI C memory management APIs (malloc, etc.) or C++ operator new, you do not need to create a memory pool. In this case, a single, default memory pool is automatically allocated for each task or process that uses SmartHeap. To use any of the memory pool functions with the default memory pool, pass the value MemDefaultPool as the memory pool parameter.

Windows 16-bit In the 16-bit Windows version of SmartHeap, memory pools are either owned by the calling task or they’re allocated as shareable under the rules of Windows 3.x (GMEM_DDESHARE). Shared memory pools are owned by the module that creates them. Each Windows EXE and each DLL that uses SmartHeap has its own distinct default memory pool (even if they each use the SmartHeap DLL). In EXEs, the default memory pool is non-shared; for DLLs, it is shared memory.

4.1.3 ANSI standard C API

malloc

Allocates a block of uninitialized memory from the default memory pool.

calloc

Allocates a block of memory from the default memory pool, initializing its contents to zero.

realloc

Changes the size of a memory block.

free

Frees a block.

These functions are all defined by the ANSI standard for the C language. This API is therefore portable, and probably already familiar to you. Each of these functions allocates from the default memory pool (see §4.1.2 for details on memory pools).

You have two choices for using this API. You can replace the functions in your C runtime library by linking with the standard SmartHeap library (which redefines malloc, etc.). In this case you do not need to include any SmartHeap header files or recompile your application — just relink.

Alternatively, if you do not wish to replace the malloc function in your C runtime library, you can include the file shmalloc.h in each of your source files and remove the shmalloc object module from the SmartHeap library. This header file provides macro versions of malloc, etc. that are defined in terms of SmartHeap functions. This technique isn’t recommended unless there are specific conflicts between SmartHeap malloc and your C runtime library. If you use this technique, you must be very careful to include shmalloc.h in each module that calls one of the above functions.

Note that in order to capture file and line information in the debug version of SmartHeap, you must include shmalloc.h in each of your source modules regardless of whether you link in the SmartHeap malloc definition.

Note In the 16-bit x86 versions of SmartHeap, these functions are far functions and accept/return far memory pointers regardless of memory model, unlike their C runtime library counterparts. The large memory model is therefore required to replace the C runtime functions malloc, etc. The macro version of malloc works in all memory models, provided that any pointers storing the result of malloc are explicitly declared to be far pointers.

4.1.4 C++ API

new type

Allocates a memory block in C++ from default memory pool.

new (pool) type

Allocates a memory block in C++ from specified memory pool.

delete

Frees a memory block allocated with new.

set_new_handler

Establishes a C++ out-of-memory handler.

These functions are the standard mechanism for dynamic memory allocation in C++. Two overloaded versions of operator new are defined for allocations: one for allocating from the default memory pool (see §4.1.2 for details on memory pools) and one for allocating from the memory pool you specify (using the placement syntax for operator new). Both of these definitions provide a global operator new for general-purpose allocation.

The SmartHeap library replaces the new and delete operators defined by your C++ runtime library with SmartHeap’s definitions. If you use only standard global operators new and delete, you do not need to include SmartHeap header files or recompile — just relink to override new and delete. To use the SmartHeap-specific version of operator new (supplying a memory pool with the placement syntax), you must include the header file smrtheap.hpp.

To capture file and line information in the debug version of SmartHeap, you must include smrtheap.h in each of your source modules, even if you use only the standard global operator new.

A useful technique is to define operators new and delete for specific C++ classes using SmartHeap fixed-size memory pools (see the entry for new in §4.2, “Function reference,” for an example). This will ensure the most efficient and convenient dynamic memory allocation for C++ class objects.

Note In the 16-bit x86 versions of SmartHeap, these functions are far functions and accept/return far memory pointers regardless of memory model, unlike their C++ runtime library counterparts. The large memory model is therefore required to replace the standard global operators new and delete. In all memory models, you can use the SmartHeap operator new with the placement syntax, or you can define your own overloaded operator new for specific classes.

4.1.5 Pointer-based API

MemAllocPtr

Allocates a memory block for a specified memory pool and returns a pointer.

MemReAllocPtr

Changes the size of a memory block.

MemFreePtr

Frees a memory block.

MemSizePtr

Returns the size of a memory block.

MemCheckPtr

Validates a pointer.

MemAllocAligned

Allocate a block with a particular alignment.

These functions represent the most useful general-purpose API for management of variable-size memory blocks. The functions are similar to the ANSI C malloc, etc., except that they allocate from a memory pool you supply. You can therefore use these functions with several memory pools to gain better control of the working set of your application and tune different memory pools for different purposes (malloc always allocates from MemDefaultPool).

These functions are also more flexible than malloc — they accept an unsigned long size parameter rather than size_t and a flags parameter to control zero-initialization and other allocation attributes.

Use MemPoolInit to allocate memory pools for use with this API.

Note In cases where you’re allocating many objects of a small, fixed size (such as a linked list), the fixed-size API (see §4.1.6 for details on fixed-size API) may be preferable because it is faster, consumes less memory, and is fragmentation free.

4.1.6 Fixed-size API

MemAllocFS

Allocates a fixed-size block from a memory pool, returning a pointer.

MemFreeFS

Frees a memory block allocated by MemAllocFS.

These functions are ideal for allocating small fixed-size objects, such as linked lists elements, tree nodes, C structures, C++ class objects, and so on. This is the fastest memory allocation API. Fixed-size memory pools incur little or no per-allocation overhead and are fragmentation free, since all blocks are of equal size.

To allocate memory pools for use with this API, use MemPoolInitFS, or use MemPoolInit in conjunction with MemPoolSetBlockSizeFS.

You can use a single function call to free all of the objects that were allocated from a pool. This is much faster and less error prone than freeing each object individually. For example, you could set up a fixed-size memory pool for a linked list with MemPoolInitFS, allocate each element with MemAllocFS, then later free the entire linked list by calling MemPoolFree.

4.1.7 Handle-based API

MemAlloc

Allocates a memory block, returning a handle.

MemReAlloc

Changes the size of a memory block allocated with MemAlloc or MemReAlloc.

MemFree

Frees a memory block allocated by MemAlloc or MemReAlloc.

MemLock

Increments the lock count of a moveable memory block, which prevents the block from being moved.

MemUnlock

Decrements a block’s lock count if previously locked with MemLock; the block can move when the lock count becomes zero.

MemFix

Increments a block’s fix count, moving the block to the fixed heap to avoid fragmenting the moveable heap.

MemUnfix

Decrements a block’s fix count, moving it back to moveable heap if fix count is zero.

MEM_REFERENCE

Macro that dereferences the memory that is identified by a given handle without locking the handle — implemented as a simple indirection in non-debug SmartHeap.

MemHandle

Retrieves the handle of the memory block at the specified address (previously returned by MemLock or MemFix).

MemIsMoveable

Determines whether a block is on the fixed or the moveable heap.

MemLockCount

Retrieves the lock or fix count of a memory block.

MemSize

Returns the actual size of a memory block.

MemSizeRequested

Returns the requested size of a memory block.

The handle-based API provides a moveable memory heap implementation, somewhat like moveable memory provided by the Windows API or relocatable memory provided by the Mac.

The SmartHeap handle-based implementation maintains dual heaps in each memory pool — one for fixed blocks and one for moveable blocks. This permits the moveable heap to be fluid and completely fragmentation-free as long as all blocks within it are unlocked. Moveable memory can be referenced at any time with the MEM_REFERENCE macro, even if the block is currently unlocked.

The MemLock function lets you retain a reference to a block until a matching MemUnlock is called. If you intend to lock a block for an extended period, MemFix is recommended. This copies the block to the fixed heap where it will not cause a “sandbar” in the moveable heap, as locked moveable blocks do. MemUnfix moves the block back to the moveable heap. Both MemLock and MemFix maintain reference counts so that nested locks and fixes will work correctly.

Note In general, the ANSI, pointer-based, or fixed-size APIs are preferable to the handle-based API, because it is much easier to deal with direct pointers to memory. The former three methods are also faster, because locking and memory movement are not occurring.

The handle-based API is suitable when you allocate several medium to large variable-size blocks from a pool, and you do not allocate any small blocks that would fill in the spaces between them. This API is also suitable when you have a large block, such as an array, that is repeatedly reallocated to a larger size. If you were to use a non-moveable memory allocator for such cases, a significant amount of memory would be lost to fragmentation.

4.1.8 Error handling

MemDefaultErrorHandler

The default error-handling function that will be in effect if you don’t implement your own.

MemSetErrorHandler

Establishes or changes the memory error-handling callback function for the current task or process.

MemErrorUnwind

You must call this function before a non-local exit (longjmp) from your custom memory error handler.

These functions are used for detecting and handling runtime error conditions, such as running out of memory, parameter errors, or double freeing.

The error handler can either cause a non-local exit (for example, longjmp), or attempt recovery (for example, free some memory and retry an allocation that has failed).

The error handler acts much like the new_handler of C++, except the SmartHeap error handler handles many error conditions aside from running out of memory. It also lets you retry on recoverable errors. If you carefully define an error handler, you can avoid testing the result of every call to an allocation function. This makes programming more convenient, reduces the chances for programming error, and produces more efficient and more readable code.

Note You can establish an error handler even if you use the ANSI allocators exclusively. Therefore, even without modifying existing source code (containing calls to malloc or new), you can greatly improve the robustness of your application.

In the debug version of SmartHeap, the error handler is invoked with detailed information on the error, including the type of error, the address of a corruption, and even the source file/line and parameters of the call where the error was detected.

4.1.9 Debugging

dbgMemCheckPtr

Validates a memory address. Capable of checking both heap and non-heap pointers.

dbgMemCheckAll

Validates all memory pools in the current process.

dbgMemSetSafetyLevel

Establishes or changes the level of error checking for the current task or process.

dbgMemSetGuardSize

Establishes the number of guard bytes to pad before and after each allocation, to detect overwrites.

dbgMemSetGuardFill

Establishes the character with which to fill guard bytes.

dbgMemSetFreeFill

Establishes the character with which to fill free blocks.

dbgMemSetInUseFill

Establishes the character with which to fill allocated blocks.

dbgMemSetCheckpoint

Establishes the context for allocations — useful for tracking down overwrites and leakage.

dbgMemSetCheckFrequency

Establishes how frequently, by default, memory pools are checked for overwrites.

dbgMemPoolSetCheckFrequency

Establishes how frequently the memory pool is checked for overwrites.

Multi-threading dbgMemScheduleChecking

Schedules checking of all memory pools in a background thread.

dbgMemDeferFreeing

Causes free blocks in all memory pools to be marked free rather than actually freed, to detect writes into free blocks.

dbgMemPoolDeferFreeing

Causes free blocks in the specified memory pool to be marked free rather than actually freed, to detect writes into free blocks.

dbgMemSetDeferSizeThreshold

Establishes the maximum size of blocks that are placed on the queue of defer-freed allocations.

dbgMemSetDeferQueueLen

Establishes the maximum number of blocks that are placed on the queue of defer-freed allocations (default for all memory pools).

dbgMemPoolSetDeferQueueLen

Establishes the maximum number of blocks that are placed on a particular pool’s queue of defer-freed allocations.

dbgMemFreeDeferred

Actually frees any blocks in all memory pools that were freed when “defer freeing” was in effect.

dbgMemPoolFreeDeferred

Actually frees any blocks in the specified memory pool that were freed when “defer freeing” was in effect.

dbgMemProtectPtr

Marks a memory block as read-only, no-free, and/or no-realloc. Any attempt to modify, free, or realloc (respectively) the block will be reported as an error.

dbgMemPoolSetName

Assigns a name to a memory pool, to facilitate identification of the pool in error reports.

dbgMemReallocMoves

Toggles a setting that causes Debug SmartHeap to always move blocks resized with realloc.

dbgMemSuppressFreeFill

Toggles a setting that controls whether Debug SmartHeap fills free blocks with a unique signature.

Windows 16-bit dbgMemReportWrongTask

Toggles a setting that causes Debug SmartHeap to report references to private memory from a task that does not own the memory.

dbgMemPtrInfo

Retrieves information about the specified allocation, including its size and where it was allocated.

dbgMemPoolInfo

Retrieves information about the specified memory pool, including its debugging settings and where it was created.

dbgMemSettingsInfo

Retrieves global Debug SmartHeap debugging settings.

dbgMemFormatErrorInfo

Formats to a string an error record that was reported to a SmartHeap error handler.

dbgMemFormatCall

Formats to a string an API that was reported to a SmartHeap error handler.

dbgMemSetDefaultErrorOutput

Establishes the output destination for the default SmartHeap error reporting mechanism (errors can be directed to any combination of interactive prompt, file, or debugging console).

dbgMemSetEntryHandler

Establishes a hook that is called at each SmartHeap entry point.

dbgMemSetExitHandler

Establishes a hook that is called at each SmartHeap exit point.

dbgMemBreakpoint

Invokes the SmartHeap error handler with an error of type MEM_BREAKPOINT.

dbgMemReportLeakage

Reports blocks that have not been freed between the specified checkpoints.

The above functions are present only in the Debug version of SmartHeap. These debug functions are used to detect bugs in your program before an error actually displays symptoms and to isolate the cause of errors post-mortem.

When using debug SmartHeap functions, you must define the preprocessor manifest constant MEM_DEBUG before you include smrtheap.h; otherwise, each of the above functions is defined as an empty macro (that is, a no-op). The runtime version of SmartHeap turns debug functions into macros, which lets you have debugging calls throughout your application source code without the need for #ifdef statements.

See Chapter 3, “Debugging,” for a detailed description of Debug SmartHeap.

4.2 Function reference

This section describes each of the SmartHeap functions in alphabetical order. If you’re looking for a function in a particular functional category but you don’t know its name, see §4.1.

Descriptions for each function follow the format illustrated here:

A brief, one-sentence description of the function.

Syntax The declaration syntax for the function. All C or C++ syntax is shown in courier.

Return value The value returned by the function.

Description A detailed description of the function’s parameters, behavior, and effects.

Comments Special considerations for the function, including platform-specific issues, usage suggestions, and performance tips.

Errors Error conditions that can arise in a call to the function. See §4.3, “Error codes,” for the meaning of each error code and the safety level needed to detect the error.

See also Related routines that might be of interest.

Example /* A code sample using the function. */

calloc

ANSI C standard zero-initializing allocator for an array of nobj elements, each of size size.

Syntax #include <shmalloc.h> macro or debug version, or
#include <stdlib.h> ANSI C function version

void *calloc(size_t nobj, size_t size);

Return value Returns a pointer to the allocated space. The return value is NULL if there is insufficient memory.

Description The calloc function allocates a block nobj x size bytes in size and initializes each bit in the block to zero.

calloc allocates from the default memory pool implicitly defined by SmartHeap for the task or process from which you call calloc. If you wish to call a memory pool function with the pool used by calloc (for example, MemPoolSize, MemPoolShrink, MemPoolCount), supply the value of the global variable MemDefaultPool for the memory pool parameter.

If nobj or size is zero, calloc returns a pointer to zero bytes of memory.

The maximum size of a single block that can be allocated with calloc is UINT_MAX minus approximately 24 bytes. Use MemAllocPtr for larger blocks on 16-bit platforms.

Comments The SmartHeap library defines the calloc function, overriding the definition present in your C runtime library. You must specify the SmartHeap library to your linker before you specify your C runtime library to ensure that you get SmartHeap’s function rather than the compiler’s function. If for some reason you do not want to override your compiler’s calloc function, you must remove the shmalloc object module from the SmartHeap library (see §2.3.3 for instructions). In this case, you can still have calloc calls go to SmartHeap by including shmalloc.h in each of your source modules — this header file defines calloc as a macro rather than as a function.

In 16-bit x86 versions of SmartHeap, calloc is a far function returning a far pointer regardless of memory model. Therefore, you must either use the large memory model or else use the macro version of calloc as described above. SmartHeap also overrides either _fcalloc or farcalloc for compilers that define one of these functions.

Errors Error code Caused by

MEM_ALLOC_ZERO Either size or nobj is zero.

MEM_BLOCK_TOO_BIG The product of nobj and size exceeds UINT_MAX - 24.

MEM_EXCEEDED_CEILING Total size of allocations in the default memory pool exceeds the size specified by MemPoolSetCeiling.

MEM_OUT_OF_MEMORY There is insufficient operating system memory to satisfy the allocation request.

See also free, malloc, MemAlloc, MemAllocFS, MemAllocPtr, MemSizePtr, new, realloc

Example #include <shmalloc.h>

typedef struct
{
char *str;
int len;
} string;

string *InitStringTable(int num_elts)
{
return (string *)
calloc(num_elts, sizeof(string));
}

dbgMemBreakpoint

Triggers a breakpoint and invokes the SmartHeap error handler.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

void dbgMemBreakpoint(void);

Return value None

Description Use dbgMemBreakpoint to stop execution at strategic points in your application. When Debug SmartHeap stops at the breakpoint, the error handler is called. If you have not installed an error handler, the breakpoint is signaled via the output specified by MemDefaultErrorOutput.

Comments This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to success result. This you have SmartHeap debugging functions in your source code without #ifdef statements.

See also dbgMemSetEntryHandler, dbgMemSetExitHandler

Errors None

Example #define MEM_DEBUG 1
#include <smrtheap.h>

/* free a data structure, then trigger a breakpoint
* so we can browse allocations to determine if all
* the pieces of the data structure have been freed
*/
typedef struct _Tree
{
struct _Tree *left;
struct _Tree *right;
char *value;
} Tree;

void freeTree(Tree *tree, Tree *root)
{
if (tree)
{
/* recursively free branches of tree */
freeTree(tree->left, root);
freeTree(tree->right, root);

/* and free this tree element */
free(tree->value);
free(tree);
}

if (tree == root)
/* entire tree has been freed: stop */
dbgMemBreakpoint();
}

dbgMemCheckAll

Checks the entire heap for overwrites.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

MEM_BOOL dbgMemCheckAll(void);

Return value Returns non-zero if all heap memory is free of overwrites, otherwise zero.

Description dbgMemCheckAll reports overwrites of heap memory to the current error handler.

This function checks all memory pools for overwrites. You can use MemPoolCheck to check an individual memory pool.

An overwrite is a write to a memory location that isn’t currently allocated to the data structure that you’re updating.

Comments This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to success result. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

Errors Error code Caused by

MEM_BAD_BLOCK An overwrite over an internal heap data structure was detected.

MEM_BAD_FREE_BLOCK An overwrite over an internal header of free heap memory was detected.

MEM_FREE_BLOCK_WRITE An overwrite into free memory was detected.

MEM_OVERWRITE An overwrite after the end of an allocation was detected.

MEM_READONLY_MODIFIED An allocation marked read-only was modified.

MEM_UNDERWRITE An overwrite before the beginning of an allocation was detected.

See also dbgMemCheckPtr

Example #define MEM_DEBUG 1
#include <smrtheap.h>

/* check on entry and exit of a buggy routine:
* if overwrites are reported on exit but not
* on entry, the overwrite has been narrowed to
* this routine
*/
void buggy()
{
dbgMemCheckAll();

...

dbgMemCheckAll();
}

dbgMemCheckPtr

Determines whether a pointer is a valid memory address.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

MEM_BOOL dbgMemCheckPtr(void *ptr,
MEM_POINTER_TYPE type, unsigned long size);

Return value dbgMemCheckPtr returns non-zero if the pointer is valid, otherwise zero.

Description dbgMemCheckPtr determines whether ptr is a valid address of type type, at which at least size bytes of memory are addressable. To determine whether a pointer has read or write access regardless of what type of memory it points to, specify type MEM_POINTER_READONLY or MEM_POINTER_READWRITE, respectively.

If you specify type MEM_POINTER_HEAP, the function returns non-zero if the value you supply for ptr is the result of any memory allocation function except the SmartHeap MemAlloc API. SmartHeap returns an error if the pointer doesn’t point to a valid heap allocation.

To validate a function pointer, specify type MEM_POINTER_CODE.

Note You can use this function to isolate dangling or wild pointers when you’re debugging your application. It is also useful for performing parameter validation within your application’s own internal APIs.

MEM_POINTER_TYPE is defined as:

typedef enum
{
MEM_POINTER_HEAP,
MEM_POINTER_CODE,
MEM_POINTER_READONLY,
MEM_POINTER_READWRITE
} MEM_POINTER_TYPE;

Comments This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to success result. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

Errors Error code Caused by

MEM_BAD_POINTER ptr does not point to heap memory.

MEM_DOUBLE_FREE ptr points to a previously freed heap allocation.

MEM_WRONG_TASK ptr points to non-shared memory not owned by the current task.

See also dbgMemCheckAll, dbgMemWalkHeap, dbgMemProtectPtr

Example #define MEM_DEBUG 1
#include <smrtheap.h>

/* example list link structure */
struct Link
{
int value;
struct Link *next;
};

/* check all links in a list for validity */
int CheckList(struct Link *link)
{
/* traverse list, returning
immediately on error */
while (link)
if (dbgMemCheckPtr(link, MEM_POINTER_HEAP,
sizeof(struct Link)))
link = link->next;
else
return FALSE;

return TRUE;
}

dbgMemDeferFreeing

Turns deferred freeing on or off.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

MEM_BOOL dbgMemDeferFreeing(MEM_BOOL bDefer);

Return value Returns non-zero if successful, otherwise zero.

Description dbgMemDeferFreeing sets or clears the default deferred freeing setting. If bDefer is non-zero, freed allocations are filled with the free fill value. However, instead of returning these allocations to the free pool for reuse, SmartHeap adds them to the queue of defer-freed allocations. Defer-freed allocations remain in the queue until you free them explicitly using dbgMemFreeDeferred or until the queue fills up and the oldest allocations in the queue are freed automatically. To change the length of the queue, use dbgMemSetDeferQueueLen.

If you turn deferred freeing off, references to free memory may not be caught because free memory will immediately be recycled for subsequent allocations.

SmartHeap is more likely to detect references to free memory if deferred freeing is on but will use less memory if deferred freeing is off. This function sets the default deferred-freeing setting for all pools. To turn deferred freeing on or off for a particular pool, use dbgMemPoolDeferFreeing.

Comments This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to success result. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

See also dbgMemFreeDeferred, dbgMemSetDeferQueueLen, dbgMemSetDeferSizeThreshold, dbgMemPoolDeferFreeing

Example #define MEM_DEBUG 1
#include <smrtheap.h>

/* extend deferral of freeing to catch
* references to free memory
*/
void detectFreeRefs()
{
/* turn deferred freeing on */
dbgMemDeferFreeing(TRUE);

/* set defer queue length to 10,000 allocations */
dbgMemSetDeferQueueLen(10000);

/* set maximum size of allocation to defer
freeing of to 100,000 bytes */
dbgMemSetDeferSizeThreshold(100000ul);
}

dbgMemFormatCall

Formats the API and parameters reported to an error handler.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

unsigned dbgMemFormatCall(
MEM_ERROR_INFO *errorInfo, char *buf,
unsigned bufsize);

Return value Returns the number of bytes actually output to buf.

Description dbgMemFormatCall formats the function name and parameters specified by the fields of errorInfo. See MemSetErrorHandler for details on the MEM_ERROR_INFO structure.

Output from this function is copied to buf. No more than bufsize characters are placed into buf — bufsize must specify the size of buf.

Important! You should only call this function from an error handler established by MemSetErrorHandler. SmartHeap calls the error handler with a pointer to a MEM_ERROR_INFO structure. Pass this value as the errorInfo parameter to dbgMemFormatCall.

Comments This function is called by dbgMemFormatErrorInfo to format the API where an error is detected and where a corrupted object was created. You can use this function to customize error formatting, but avoid parsing the parameter fields of MEM_ERROR_INFO, which differ for each SmartHeap API.

This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to zero. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

See also dbgMemFormatErrorInfo, MemSetErrorHandler, MemDefaultErrorHandler, dbgMemSetDefaultErrorOutput

Example #define MEM_DEBUG 1
#include <smrtheap.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_CALL 256
/* example SmartHeap error handler that calls
dbgMemFormatCall to customize error output
*/
MEM_BOOL MEM_CALLBACK MyErrorHandler(
MEM_ERROR_INFO *errorInfo)
{
char buf[MAX_CALL+1];

fputs("Memory error detected in: ", stderr);
dbgMemFormatCall(errorInfo, buf, MAX_CALL);
fputs(buf, stderr);

abort();
return 0;
}

dbgMemFormatErrorInfo

Formats the error information reported to an error handler.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

unsigned dbgMemFormatErrorInfo(
MEM_ERROR_INFO *errorInfo, char *buf,
unsigned bufsize);

Return value Returns the number of bytes actually output to buf.

Description dbgMemFormatErrorInfo formats information specified by the fields of errorInfo. This information includes the API and location where an error was detected, the API and location where a corrupted object was created, and the address and contents of the corrupted object. For details on the MEM_ERROR_INFO structure, see MemSetErrorHandler.

Output from this function is copied to buf. No more than bufsize characters are placed into buf — bufsize must specify the size of buf.

Important! You should only call this function from an error handler established by MemSetErrorHandler. SmartHeap calls the error handler with a pointer to a MEM_ERROR_INFO structure. Pass this value as the errorInfo parameter to dbgMemFormatErrorInfo.

Comments You can use this function to customize error input/output, but avoid parsing and formatting the fields of MEM_ERROR_INFO.

This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to zero. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

See also dbgMemFormatCall, MemSetErrorHandler, MemDefaultErrorHandler, dbgMemSetDefaultErrorOutput

Example #define MEM_DEBUG 1
#include <smrtheap.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_OUT 800
/* example SmartHeap error handler that calls
dbgMemFormatErrorInfo to customize I/O
*/
MEM_BOOL MEM_CALLBACK MyErrorHandler(
MEM_ERROR_INFO *errInfo)
{
char buf[MAX_OUT+1];

fputs("Fatal Memory Error!\n", stderr);
dbgMemFormatErrorInfo(errInfo,buf, MAX_OUT);
fputs(buf, stderr);

abort();
return 0;
}

dbgMemFreeDeferred

Frees all allocations in the queue of defer-freed allocations in all memory pools.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

MEM_BOOL dbgMemFreeDeferred(void);

Return value Returns non-zero if successful, otherwise zero.

Description dbgMemFreeDeferred deallocates any allocations, in all memory pools, that were marked as free while deferred freeing was in effect. Use dbgMemDeferFreeing to control the current deferred freeing status. You can call this function whether or not deferred freeing is currently in effect.

Note Use this function to reclaim memory whose freeing was previously deferred. You might call this function in response to detecting a low-memory condition. You might also call it after safely exiting an area of code where you suspect overwrites.

Comments This function is available only in the Debug SmartHeap library. If you do not define the macro symbol MEM_DEBUG before including smrtheap.h, the function is defined as a macro that expands to success result. This lets you have SmartHeap debugging functions in your source code without #ifdef statements.

See also dbgMemDeferFreeing, dbgMemPoolFreeDeferred

Example #define MEM_DEBUG 1
#include <smrtheap.h>

/* reclaim memory from the queue of defer-freed
* allocations, in response to an out-of-memory
* condition
*/
MEM_BOOL MEM_CALLBACK MyErrorHandler(
MEM_ERROR_INFO *errorInfo)
{
/* first call default error handler */
MEM_BOOL bRetry =
MemDefaultErrorHandler(errorInfo);

/* check for out-of-memory condition */
if (errorInfo->errorCode == MEM_OUT_OF_MEMORY)
{
/* free memory from defer-freed allocations
so that the current allocation can succeed */
dbgMemFreeDeferred();
}

return bRetry;
}

/* establish the above error handler as follows */
main()
{
MemSetErrorHandler(MyErrorHandler);

...
}

dbgMemPoolDeferFreeing

Controls delayed freeing of blocks in a memory pool.

Syntax #define MEM_DEBUG 1
#include <smrtheap.h>

MEM_BOOL dbgMemPoolDeferFreeing(MEM_POOL pool,
MEM_BOOL bDefer);

Return value Returns non-zero if