相比崩溃,内存泄漏是一种比较容易排查的BUG,只需按照即定的操作步聚,重现一次内存泄露,即可找出内存泄露所在的代码行。
现在介绍一下如何利用windbg提供的工具来排查内存泄漏问题.
首先需要设置PDB文件的路径, 设置环境变量:变量名为_NT_SYMBOL_PATH, 变量值为PDB文件所在的路径我的设置是:C:\WINDOWS\Symbols;C:\WINDOWS\system32;E:\Project\pdb
修改注册表使操作系统对每一次内存分配操作时的调用栈进行记录:
gflags -i ProgramName.exe +ust
C)利用UMDH工具抓取软件在两个时刻的调用记录.
umdh -pn:ProgramName.exe -f:firstTraceFile.txt
umdh -pn:ProgramName.exe -f:secondTraceFile.txt
D)比较两次抓取的调用记录的差别
umdh firstTraceFile.txt secondTraceFile.txt > result.txt
E)分析result.txt, 判断这段时间内导到内存泄漏的函数调用栈
以下是我的一个测试程序的结果:
测试过程是,先执行5次NEW操作,再执行3次delete操作
//
// Each log entry has the following syntax:
//
// + BYTES_DELTA (NEW_BYTES - OLD_BYTES) NEW_COUNT allocs BackTrace TRACEID
// + COUNT_DELTA (NEW_COUNT - OLD_COUNT) BackTrace TRACEID allocations
// ... stack trace ...
//
// where:
//
// BYTES_DELTA - increase in bytes between before and after log
// NEW_BYTES - bytes in after log
// OLD_BYTES - bytes in before log
// COUNT_DELTA - increase in allocations between before and after log
// NEW_COUNT - number of allocations in after log
// OLD_COUNT - number of allocations in before log
// TRACEID - decimal index of the stack trace in the trace database
// (can be used to search for allocation instances in the original
// UMDH logs).
//
2f70 ( 1fa0 - 4f10) 2 allocsBackTrace360
- 3 ( 2 - 5)BackTrace360allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
MSVCRTD!_heap_alloc_base+0000013C (malloc.c, 200)
MSVCRTD!_heap_alloc_dbg+000001A2 (dbgheap.c, 378)
MSVCRTD!_nh_malloc_dbg+00000049 (dbgheap.c, 248)
MSVCRTD!_malloc_dbg+0000001F (dbgheap.c, 165)
MFC42D!operator new+00000024 (afxmem.cpp, 373)
MFC42D!operator new+00000016 (afxmem.cpp, 65)
te!CTeDlg::OnButton1+00000037 (E:\test\teDlg.cpp, 180)
MFC42D!_AfxDispatchCmdMsg+000000A2 (cmdtarg.cpp, 88)
MFC42D!CCmdTarget::OnCmdMsg+00000274 (cmdtarg.cpp, 302)
MFC42D!CDialog::OnCmdMsg+00000024 (dlgcore.cpp, 97)
MFC42D!CWnd::OnCommand+00000138 (wincore.cpp, 2099)
MFC42D!CWnd::OnWndMsg+00000053 (wincore.cpp, 1608)
MFC42D!CWnd::WindowProc+0000002E (wincore.cpp, 1596)
MFC42D!AfxCallWndProc+000000ED (wincore.cpp, 215)
通过以上线程调用栈可以很容易地查出引起内存泄漏的原因。