Debugging memory heaps

XL C/C++ provides two sets of functions for debugging memory problems:

Both sets of debugging functions have their benefits and drawbacks. The one you choose to use depends on your program, your problems, and your preference.

The heap-checking functions perform more general checks on the heap at specific points in your program. You have greater control over where the checks occur. The heap-checking functions also provide compatibility with other compilers that offer these functions. You only have to rebuild the modules that contain the heap-checking calls. However, you have to change your source code to include these calls, which you will probably want to remove in your final code. Also, the heap-checking functions only tell you if the heap is consistent or not; they do not provide the details that the debug memory management functions do.

On the other hand, the debug memory management functions provide detailed information about all allocation requests you make with them in your program. You don't need to change any code to use the debug versions; you need only specify the -qheapdebug option.

A recommended approach is to add calls to heap-checking functions in places you suspect possible memory problems. If the heap turns out to be corrupted, you can rebuild with -qheapdebug.

Regardless of which debugging functions you choose, your program requires additional memory to maintain internal information for these functions. If you are using fixed-size heaps, you might have to increase the heap size in order to use the debugging functions.

Related information

Functions for checking memory heaps

The header file umalloc.h declares a set of functions for validating user-created heaps. These functions are not controlled by a compiler option, so you can use them in your program at any time. Regular versions of these functions, without the _u prefix, are also available for checking the default heap. The heap-checking functions are summarized in the following table.

Table 12. Functions for checking memory heaps
Default heap function User-created heap function Description
_heapchk _uheapchk Checks the entire heap for minimal consistency.
_heapset _uheapset Checks the free memory in the heap for minimal consistency, and sets the free memory in the heap to a value you specify.
_heap_walk _uheap_walk Traverses the heap and provides information about each allocated or freed object to a callback function that you provide.

To compile an application that calls the user-created heap functions, see Compiling and linking a program with user-created heaps.

Functions for debugging memory heaps

Debug versions are available for both regular memory management functions and user-defined heap memory management functions. Each debug version performs the same function as its non-debug counterpart, and you can use them for any type of heap, including shared memory. Each call you make to a debug function also automatically checks the heap by calling _heap_check (described below), and provides information, including file name and line number, that you can use to debug memory problems. The names of the user-defined debug versions are prefixed by _debug_u (for example, _debug_umalloc), and they are defined in umalloc.h.

For a complete list and details about all of the debug memory management functions, see Appendix. Memory debug library functions.

Table 13. Functions for debugging memory heaps
Default heap function Corresponding user-created heap function
_debug_calloc _debug_ucalloc
_debug_malloc _debug_umalloc
_debug_heapmin _debug_uheapmin
_debug_realloc n/a
_debug_free n/a

To use these debug versions, you can do either of the following:

To compile an application that calls the user-created heap functions, see Compiling and linking a program with user-created heaps.

Notes:
  1. When the -qheapdebug option is specified, code is generated to pre-initialize the local variables for all functions. This makes it much more likely that uninitialized local variables will be found during the normal debug cycle rather than much later (usually when the code is optimized).
  2. Do not use the -brtl option with -qheapdebug.
  3. You should place a #pragma strings (readonly) directive at the top of each source file that will call debug functions, or in a common header file that each includes. This directive is not essential, but it ensures that the file name passed to the debug functions cannot be overwritten, and that only one copy of the file name string is included in the object module.

Additional functions for debugging memory heaps

Three additional debug memory management functions do not have regular counterparts. They are summarized in the following table.

Table 14. Additional functions for debugging memory heaps
Default heap function Corresponding user-created heap function Description
_dump_allocated _udump_allocated Prints information to stderr about each memory block currently allocated by the debug functions.
_dump_allocated_delta _udump_allocated_delta Prints information to file descriptor 2 about each memory block allocated by the debug functions since the last call to _dump_allocated or _dump_allocated_delta.
_heap_check _uheap_check Checks all memory blocks allocated or freed by the debug functions to make sure that no overwriting has occurred outside the bounds of allocated blocks or in a free memory block.

The _heap_check function is automatically called by the debug functions; you can also call this function explicitly. You can then use _dump_allocated or _dump_allocated_delta to display information about currently allocated memory blocks. You must explicitly call these functions.

Using memory allocation fill patterns

Some debug functions set all the memory they allocate to a specified fill pattern. This lets you easily locate areas in memory that your program uses.

The debug_malloc, debug_realloc, and debug_umalloc functions set allocated memory to a default repeating 0xAA fill pattern. To enable this fill pattern, export the HD_FILL environment variable.

The debug_free function sets all free memory to a repeating 0xFB fill pattern.

Skipping heap checking

Each debug function calls _heap_check (or _uheap_check) to check the heap. Although this is useful, it can also increase your program's memory requirements and decrease its execution speed.

To reduce the overhead of checking the heap on every debug memory management function, you can use the HD_SKIP environment variable to control how often the functions check the heap. You will not need to do this for most of your applications unless the application is extremely memory intensive.

Set HD_SKIP like any other environment variable. The syntax for HD_SKIP is:

set HD_SKIP=increment,[start]

where:

increment
Specifies the number of debug function calls to skip between performing heap checks.
start
Specifies the number debug function calls to skip before starting heap checks.
Note:
The comma separating the parameters is optional.

For example, if you specify:

set HD_SKIP=10

then every tenth debug memory function call performs a heap check. If you specify:

set HD_SKIP=5,100

then after 100 debug memory function calls, only every fifth call performs a heap check.

When you use the start parameter to start skipping heap checks, you are trading off heap checks that are done implicitly against program execution speed. You should therefore start with a small increment (like 5) and slowly increase until the application is usable.

Using stack traces

Stack contents are traced for each allocated memory object. If the contents of an object's stack change, the traced contents are dumped.

The trace size is controlled by the HD_STACK environment variable. If this variable is not set, the compiler assumes a stack size of 10. To disable stack tracing, set the HD_STACK environment variable to 0.