Memory Leaks are a common error in programming, especially when the language used to write the Code has no in-built automatic garbage collection mechanism. A memory leak can greatly reduce the performance of the system by reducing the amount of available memory especially when the amount of memory available in a system is very limited (in the case of portable systems and embedded applications) and when the program runs for long periods of time (such as background tasks on servers). Due to the prevalence of the memory leak bugs, a number of debugging tools such as IBM Rational Purify, Bounds Checker, memwatch etc. have been developed. Another such tool is User Mode Heap Dump (UMDH). The advantage of using UMDH is that it is very light-weight and fairly all the memory leaks in an application can be traced along with the line number in the source code where the memory has been leaked in a simple and easier way.
The UMDH utility dumps information about the heap allocations of a process and this information include:
· the ‘callstack’ for each allocation,
· the number of allocations that are made through that ‘callstack’, and
· the number of bytes that are consumed through that ‘callstack’.
The UMDH utility also helps compare two UMDH logs to provide an analysis of the difference between them. This information is actually used to check whether there is a memory leak or not.
Pre-requisites for using UMDH
Installing the UMDH Utility:
The UMDH utility is included with the Debugging Tools for Windows. It can be downloaded from the following Web site:
http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx
After installing the utility, the System PATH environment variable must be set to the location where the UMDH is installed.
Fig. 1: Setting the System PATH Environment Variable
The Windows Symbol Package for Windows XP must be downloaded from the Microsoft Web Site mentioned below and the path where the symbol files are installed must be added to the ‘_NT_SYMBOL_PATH’ environment variable. This has to be done to get the details of the Windows Function Calls in the Stack Trace.
The Windows Symbol package can be downloaded from the Web Site:
http://www.microsoft.com/whdc/DevTools/Debugging/symbolpkg.mspx
Fig. 2: Setting the ‘_NT_SYMBOL_PATH’ Environment Variable
Then, the Global Flags has to be set to enable the creation of the User Mode Stack Trace Database. This is just to let the operating system know that the kernel needs to track the memory allocations made by the application.
For example, if the heap dump is required for ‘Reg.exe’. First, the stack trace acquisition must be enabled for ‘Reg.exe’. By default, this feature is not enabled. The command to enable this feature is:
Fig. 3: Enabling the Stack Traces for ‘Reg.exe’.
Note: The command does not enable stack tracing for processes that are already running. It only enables the stack tracing for all the future executions of ‘Reg.exe’.
The flag can also be set through the ‘GFLAGS’ user interface (run Gflags.exe without any arguments in the command prompt to get the user interface).
Fig. 4: Enabling the Stack Traces for ‘Reg.exe’ from the GUI of ‘Gflags’ Utility.
The -ust option for ‘gflags’ can be used to disable the stack tracing when the debugging is finished.
Using UMDH
After the program is started, the Process ID (PID) of the process must be determined. The PID of the application can be obtained from the output of the ‘tlist’ application or the Task Manager.
The UMHD utility can be used now to get the information regarding the heap allocations of a process.
The Command to be used is:
For Example,
If the Process ID is 2204 and the Output File Name is Log01.log, the command to be given is:
The complete heap dump of the ‘Reg’ Process is now in the ‘Log01.log’ file. This file shows all the allocations that were made and the call stacks where the allocations were made.
The Heap Dump is obtained after each successive execution of the application or after the execution of a particular feature in the application. The subsequent executions must be equivalent. For example, if a certain procedure is followed [Triggering the events in the GUI or running a specific module in the application etc.] during the first execution of the application, the same must be followed in the subsequent execution.
The general principle of operation is that UMDH is typically run two (or more times), once to capture a “baseline” snapshot of the process after it has finished initializing (as there are expected to always be a number of outstanding allocations while the process is running that would not be normally expected to be freed until process exit time.
UMDH is then run again in a special mode that is designed to essentially do a logical “diff” between the “baseline” snapshot and the “leaked” snapshot, filtering out any allocations that were present in both of them and returning a list of new, outstanding allocations, which would generally include any leaked heap blocks. It matches the back traces from each file and calculates the increase in bytes allocated for each back trace. These are then displayed in descending order of size of leak. The first line of each backtrace output shows the size of the leak in bytes, followed by the (last-first) difference in parentheses.
The Syntax for the Comparison is:
umdh File01 File02 > File03
where File01 and File02 are the Log Files obtained in two different times the former at an earlier time and the latter at a later time. File03 is the File where the Comparison Information is to be saved.
For Example,
umdh File01.log File02.log > Comparison.log
The various options that can be used with the UMDH utility are:
-d : to display the Output in Decimal (default is Hexadecimal).
-v : To get the verbose output which includes the actual back traces as well as summary information.
-l : To get the file and line number information or the traces.
Demo:
I used a Win32 Test Application which leaks Memory after each Command Button Click. After enabling the ‘User Mode Stack Trace Database’, I started the application and its Process ID was ‘408.
I clicked the Command Button Once and executed the UMDH Tool to create a baseline snapshot of the heap allocations using the following command:
Then, I clicked the Command Button again and executed the UMDH Tool to create the second snapshot of the Heap Allocations. The Command used was the same as the above except that the Output File Name was changed to ‘Log02.log’.
Note: As each output File is a discrete entity, data is not appended to the end of each file. So, if a batch file is intended to run every ten minutes, we’ll have to ensure that the output file name is different for each snapshot.
After taking the two snapshots of the heap allocation, the UMDH Tool can be used to compare the two files and create an output file. The Command used was:
Each Log Entry in the ‘Diff.log’ has the Following Syntax:
One such Log Entry had the Following Data:
From the above Output, one can infer that Memory was leaked in the Line No. 219 in the ‘TestAppl01.cpp’ File.
The memory leaks are listed in descending order of bytes leaked; each will be followed by the complete stack trace of the allocation call. Depending on the cause, this may either pinpoint the bug / leak, or at least show a good place to set a breakpoint for debugging.
I’ve embedded the Code for the Sample Application and the Logs which were obtained.
Conclusion
UMDH is a fairly simple tool to use and it can very effectively used to pin-point the location of memory leak. All we need to do is to have the Symbol File ( pdb ) of the Application and the Symbol Files of the Windows DLL’s. I’ve included a very simple application as an example just to drive home the idea of using this tool. This tool even can be used to find memory leaks in an application which has a very large code base.
References
0 comments:
Post a Comment