Debugging Tools for Windows |
The user-mode dump heap (UMDH) utility works with the operating system to analyze Windows heap allocations for a specific process. UMDH locates which routine in a specific process is leaking memory.
UMDH is included in Debugging Tools for Windows. For full details, see UMDH.
If you have not already determined which process is leaking memory, do that first. For details, see Using Performance Monitor to Find User-Mode Memory Leaks.
The most important data in the UMDH logs are the stack traces of the heap allocations. To determine whether a process is leaking heap memory, analyze these stack traces.
Before using UMDH to display the stack trace data, you must use GFlags to configure your system properly. GFlags is included in Debugging Tools for Windows.
The following GFlags settings enable UMDH stack traces:
Before using UMDH, you must also have access to the proper symbols for your application. UMDH uses the symbol path specified by the environment variable _NT_SYMBOL_PATH. Set this variable equal to a path containing the symbols for your application. If you also include a path to Windows symbols, the analysis may be more complete. The syntax for this symbol path is the same as that used by the debugger; for details, see Symbol Path.
For example, if the symbols for your application are located at C:\MySymbols, and you want to use the public Microsoft symbol store for your Windows symbols, using C:\MyCache as your downstream store, you would use the following command to set your symbol path:
After making these preparations, you can use UMDH to capture information about the heap allocations of a process. To do so, follow this procedure:
UMDH can compare two different log files and display the change in their respective allocation sizes. You can use the greater-than symbol (>) to redirect the results into a third text file. You may also want to include the
Total increase == 5320
For each call stack (labeled "BackTrace") in the UMDH log files, there is a comparison made between the two log files. In this example, the first log file (Log1.txt) recorded 0x9DF0 bytes allocated for BackTrace00B53, while the second log file recorded 0xF110 bytes, which means that there were 0x5320 additional bytes allocated between the time the two logs were captured. The bytes came from the call stack identified by BackTrace00B53.
ntdll!RtlDebugAllocateHeap+0x000000FD
ntdll!RtlAllocateHeapSlowly+0x0000005A
ntdll!RtlAllocateHeap+0x00000808
MyApp!_heap_alloc_base+0x00000069
MyApp!_heap_alloc_dbg+0x000001A2
MyApp!_nh_malloc_dbg+0x00000023
MyApp!_nh_malloc+0x00000016
MyApp!operator new+0x0000000E
MyApp!DisplayMyGraphics+0x0000001E
MyApp!main+0x0000002C
MyApp!mainCRTStartup+0x000000FC
KERNEL32!BaseProcessStart+0x0000003D
This UMDH output shows that there were 0x5320 (decimal 21280) total bytes allocated from the call stack. These bytes were allocated from 0x14 (decimal 20) separate allocations of 0x428 (decimal 1064) bytes each.
The call stack is given an identifier of "BackTrace00B53," and the calls in this stack are displayed. In reviewing the call stack, you see that the DisplayMyGraphics routine is allocating memory through the new operator, which calls the routine malloc, which uses the Visual C++ run-time library to obtain memory from the heap.
Determine which of these calls is the last one to explicitly appear in your source code. In this case, it is probably the new operator because the call to malloc occurred as part of the implementation of new rather than as a separate allocation. So this instance of the new operator in the DisplayMyGraphics routine is repeatedly allocating memory that is not being freed.