Each block of allocated memory within a heap consists of a data area, which starts at the address returned by the allocating function, as well as a control area adjacent to the data area, which is needed by the memory management functions to free the memory properly when you deallocate the memory. If you overwrite a control structure in the heap (for example, by writing to elements outside the allocated bounds of an array, or by copying a string into too small a block of allocated memory), the control information is corrupted and might cause incorrect program behavior even if the data areas of other allocated blocks are not overwritten.
Consider the following points when you are trying to locate heap errors:
To detect heap errors, you can compile your program to use the heap-checking versions of memory management functions (for information about the -qheapdebug compiler option, see the related debug compiler option topic). When you run a program compiled with this option, each call to a memory management function causes a heap check to be performed on the default heap. This heap check involves checking the control structures for each allocated block of memory within the heap, and ensuring that none was overwritten. If an error is encountered, the program terminates and information is written to standard error including the address where heap corruption occurred, the source file and line number at which a valid heap state was last detected, and the source file and line number at which the memory error was detected.
Heap checking is only enabled for the default heap used by each executable. If the debug versions of the memory management functions do not report heap corruption and you still suspect a problem, you might be using additional heaps and corrupting them.
You can pinpoint the cause of a heap error from within the debugger, provided the heap causing the error is known to be the default heap, by continually narrowing down the gap between the last line at which the heap was valid, and the first line at which corruption occurred. Use a combination of run commands, step commands, line and function breakpoints, and the Perform Heap Check on Stop setting to narrow the scope of your search. For information about this setting, see the related topic.
For semantically-incorrect programs, Perform Heap Check on Stop is intrusive in that it might cause different results where a program is incorrectly accessing data on the stack. This is because Perform Heap Check on Stop causes the process and thread being debugged to call a heap check function each time execution stops, and this heap check function affects the safe area of the stack by overwriting part of that area with its stack frame. For example, if a called function returns the address of a local variable, that local variable's contents are accessible from the calling function, and does not change, as long as the stack frame used by the called function is not overwritten by a subsequent call. However, if you issue a step return from the called function while Perform Heap Check on Stop is enabled, the heap checking function is called immediately on return from the called function, and the memory pointed to by the returned pointer might have been overwritten by the stack frame of the heap-checking function.
Heap checking within the debugger has a high overhead cost for step commands, because the heap is checked after each step. If you are stepping through large sections of code, or frequently stopping at breakpoints, and you find debug performance too slow, try turning on Perform Heap Check on Stop only in those areas you suspect are causing heap errors.