https://www.codeproject.com/Articles/108529/LeakDiag-An-Effective-Memory-Leak-Analysis-Tool
这个似乎是老版本的。
Introduction
Memory leak problems are relatively complex and challenging when the code base is huge and complex, the problem increases if our application is running on server for multiple days. As this is very common problem with C++ code, there are many tools developed to analyze memory leaks, such as Rational Purifier, Bounds Checker, but these tools are not freely available. If you want to find memory leaks in your program without investing in such tools, then please go ahead and read this article.
Where Should I Get This Tool?
This is a tool developed and distributed by Microsoft and is freely available on Microsoft’s FTP atftp://ftp.microsoft.com/PSS/Tools/Developer%20Support%20Tools/LeakDiag/. Download and install this tool on the system where our application is running. (This might be your desktop or a server machine.)
What is LeakDiag ?
This is freeware used to detect memory leaks in small as well as large scale enterprise applications, very simple and handy to use. We can use this tool to find memory leaks of simple EXE as well as Windows Service; the good thing here is I need not stop the application to start leak analysis. The output of this tool is an XML file which contains all stack frames that have allocated the memory and not freed up at the time of snapshot. We will see this procedure in detail below. We need to do some initial settings before we actually start collecting logs.
Initial Settings
The first thing we need to do is to set public symbol path (srv*c:\symcache*http://msdl.microsoft.com/download/symbols). Go to open the tool and go to tools -> Options. Set the public symbol path as well as your local symbol path here, refer to the below figure:
The check box Resolve symbols when loggingstates whether we want to resolve the symbols at the time of logging or not. This option can be checked if our application is small and doesn’t acquire much of RAM, but for applications which use huge memory space and which run on server for a long time, resolving symbols at the time of logging will not be a good option as the system hangs while collecting the stack frames and resolving symbols for each of them (In large scale applications, there can be large number of stack frames which doesn’t). I suggest to resolve symbols later so do not check this checkbox. You also need to mention the log file path where you want to store the generated logs. Click Ok and you are done with initial required settings.
Attaching to a Process
The main window of LeakDiag
will look like below:
Here in the list box, you will see all the available processes as how we could see them in Task Manager, and there is another list which asks about Memory Allocators. Below are the meanings of all listed allocators:
- Virtual Allocator (
VirtualAlloc
) - Windows Heap Allocator (
HeapAlloc
)[DEFAULT] - COM Allocator (
CoTask
) - C Runtime Allocator (
msvcrt new
) - TLS Slot Allocator (
TlsAlloc
)
Out of all above allocators, the important ones are Windows Heap Allocators and COM Allocators, which cause leaks in most of the cases. We can select more than one allocator as well at a time by pressing ctrl key.
Now after selecting the appropriate allocator, click Start to start the analysis of your code, after some tome and interval, take the snapshot of stacks by clicking log button and theLeakDiag
will take some time to log as per the selected option (Resolve Symbols). We can take snapshots after fixed interval by clicking log button. This will collect all stack frames which have allocated the memory and are not freed up till then. We should take as many snapshots as possible, more the snapshots it is easier to find out the leaking stacks. We can also automate the process of snapshots taking by modifyingautodiag.ini, this file you can find in the folder where theLeakDiag
is installed. Also this setting can be done by modifying the registry key as below:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\LeakDiag\<a name="EnableAutoDumpReg">EnableAutoDump</a>
This key lets you enable or disable the Auto Dump Feature.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\LeakDiag\AutoDumpInterval
This key lets you select the interval at which you want the logs to be generated.
Okay, now we have logs collected after regular interval and its time to analyze the logs.
Analyzing Logs
Before we go for analyzing the logs, if we have not resolved the Symbols (The checkbox I mentioned in the above section), then this is a time to do it. Open a command prompt and go to the installed folder ofLeakDiag
, then run the sdecode.exe command to check the usage, you will find below usage-
sdecode /z <path to .dmp file> [/y <sympath>] [/i <imagepath>] inputfile outputfile
i.e.:
sdecode /z c:\memtest.dmp /y c:\winnt;srv*\\symbols\symbols Log123.xml NewLog.xml
This utility is very useful as we can collect the unresolved stack frames without any performance impact on the process and later we can resolve symbols of it. Remember that the naming convention of files should not be modified or else we will not be able to analyze them using LDParser
or LDGrapher
.
There are three ways we can analyze the logs in XML file.
1. XML Reading and Manually Analyzing Them
This is a little trick and time consuming process of analyzing the stack frames but this gives us the clear and better picture of leaks in process, mastering in reading XML files will make it easier to understand theLDParser
and LDGrapher
tools as well.
The XML mainly consist of three sections:
- Schema of XML
LEAKS
tag, in which all the stack frames with memory allocated in it and not freed are includedSUMMERY_INFO
tag, this tag contains some process and memory info and modules included in a process
See the stack frames in the second section. This section contains multiple STACK
tags which mention the stack frames:
<STACK numallocs="05" size="015833497" totalsize="079167488">
<STACKSTATS>
<SIZESTAT size="01048576" numallocs="01" type="MEM_RESERVE"/>
<SIZESTAT size="02097152" numallocs="01" type="MEM_RESERVE"/>
<SIZESTAT size="0524288" numallocs="01" type="MEM_RESERVE"/>
<ASSOCIATED_STACKS stackid="23AB8548" type="MEM_COMMIT"
numallocs="02" totalsize="024575"/>
<ASSOCIATED_STACKS stackid="1F9C3EE8" type="MEM_COMMIT"
numallocs="01" totalsize="024576"/>
<ASSOCIATED_STACKS stackid="1F9C4008" type="MEM_COMMIT"
numallocs="01" totalsize="012288"/>
</STACKSTATS>
<FRAME num="0" dll="" function="" offset="0xC0DECAFE"
addr="0xc0decafe" filename="" line=""/>
<STACKID>23AB40E8</STACKID>
</STACK>
Total size allocated by stack is shown in the above highlighted portion in size and totalsize.ASSOCIATED_STACKS
shows all associated stacks in that region; with little more intelligence we can read the affected stacks from multiple files (one file per screenshot, the logs which we have created above) identified bySTACKID
and see where the actual leak is happening. For this, we need to take multiple files and track each stack in these files one by one, if the totalsize of stack value goes on increasing or even if it is remaining constant for a long time, then we can take that stack as a doubtful stack and check if memory allocated by that particular stack is getting freed correctly. Repeat the above process with all stacks which are having high total size value and track the leaks accordingly, you might find this process a little tedious but once you master it, this will be a best process you can find.
Alternately, you can also write a script which will parse the XML for you and create an XSL file; many experienced developers follow this technique.
2. LDParser
This is tool we can use to parse the generated XML files and see the data in tabular format; I searched it on web but couldn’t get it.
3. LDGrapher
This is a redistributable tool provided by Microsoft and is available on Microsoft FTP server. We can install this on our local and provide the generated XML files as an input and this tool will give us the graphical representation of our stacks as shown below.
![LDGrapher.JPG](https://i-blog.csdnimg.cn/blog_migrate/fb2da9e283338b7c6586e6643f05300d.jpeg)
Here LDGrapher
picks up most affected stacks and shows it to us with different colors. We can double click on any line to open the corresponding stack and see what the start point of that allocation is.
To see the stacks in LDGrapher
, we need to select only one type of allocation and the subsequent screenshot files of that allocation, or else we will not be able to see any output.
I hope this is pretty much for LeakDiag
and don’t hesitate to add any new information if you find it.
History
- 10th September, 2010: Initial post
License
This article, along with any associated source code and files, is licensed underThe Code Project Open License (CPOL)
http://mcfunley.com/using-leakdiag-to-debug-unmanaged-memory-leaks
It's the second-most-common combination of search terms, trailing "hank goldberg picks" by a hell of a lot. I don't think the searches are coming from the same demographic. Anyway, I thought I would write up one of the easiest techniques that I'm aware of for debugging a memory leak in unmanaged code. This one doesn't touch WinDbg, but rather uses a few other Microsoft PSS tools specifically built for this purpose.
For this example, I fired up the MFC wizard and created a new scratch application. To that I added some logic to leak roughly 2K of memory every tenth of a second.
#include <vector> using namespace std; BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_TIMER() END_MESSAGE_MAP() // Incredibly stupid memory leak void CMainFrame::OnTimer(UINT_PTR nIDEvent) { UNREFERENCED_PARAMETER(nIDEvent); vector<int>* pvec = new vector<int>(); for(int i = 0; i < 500; i++) { pvec->push_back(i); } } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { // ... this->SetTimer(1, 100, NULL); }
Supposing we had not done this on purpose, it would be clear from looking at the process in Perfmon that we were dealing with a memory leak. The Private Bytes counter for this process grows steadily while the application is doing nothing in particular.
The tools that we'll be using to look at this problem are LeakDiag, LDParser, and LDGrapher. You can download them all fromftp://ftp.microsoft.com/PSS/Tools/ (LeakDiag and LDParser are bundled together).
After opening the problem application, start LeakDiag.exe. In Tools->Options, we want to increase the stack depth to the maximum (32). The reason for this is because in an application written in any medium to high level language you are typically pretty far from the actual call to malloc when you are leaking memory.
There are a few options available (on the main dialog) for the specific allocator to monitor. Several may generate hits for the same leak (The CRT malloc will ultimately call the NT APIs, for example), but try to pick the one that most describes your application. Click Start and create a few logs as the leak manifests itself. In the MFC application I wrote, the leak is occurring constantly. Your application may need to run for many hours before you can get any worthwhile data.
After doing this, you can use the LDParser application to open up one of the log files. You'll see something like this:
The upper-right pane is a list of unique stack traces when the specified allocator was invoked. The list should be sorted by the total amount of data allocated by each. The bottom pane shows the stack trace for the active stack ID. In my case, the stack allocating the most memory is my intentional leak (notice that CMainFrame::OnTimer
is in frame ten).
If your situation is more complicated than mine, as it almost certainly will be, there is one other tool you should be aware of. LDGrapher can take a set of logs generated by LeakDiag and generate a set of graphs of allocations over time. Here is the output of my application over a few minutes:
Each stack ID is represented by a line on the graph. Hopefully, this will help some of you debugging unmanaged memory leaks.