windows下使用umdh定位C++内存泄漏
如需转载请标明出处:https://blog.csdn.net/itas109
技术交流:129518033
环境:
OS: windows 10(1909 内部版本18363)
windbg: 6.12 x64
UMDH: 6.1.7650
前言
用户模式转储堆 (UMDH) 实用工具与操作系统一起用于分析特定进程 Windows 堆分配。 UMDH 查找特定进程中的哪个例程正在泄漏内存。
1. 安装umdh
2. 使用umdh截取内存快照
2.1 命令行方式
- 开启堆栈追踪功能
注意:该功能开始后会影响程序性能,生产环境慎用。
"C:\Program Files\Debugging Tools for Windows (x64)\gflags" -i main.exe +ust
- 设置应用程序pdb路径(系统pdb路径可选填)
SET _NT_SYMBOL_PATH=D:\MemoryLeakTest\build
或
SET _NT_SYMBOL_PATH=D:\MemoryLeakTest\build;srv*c:\symbols*http://msdl.microsoft.com/download/symbols
- 截取当前内存快照
"C:\Program Files\Debugging Tools for Windows (x64)\umdh" -pn:main.exe -f:Snap1.log
- 程序运行一段时间或执行某些怀疑有泄漏的操作
此处,测试程序main.exe每次按回车,都会申请新内存
- 截取运行后的快照
"C:\Program Files\Debugging Tools for Windows (x64)\umdh" -pn:main.exe -f:Snap2.log
- 分析结果
注意:此时可能会下载系统所需pdb,需要等待一会
"C:\Program Files\Debugging Tools for Windows (x64)\umdh" -d Snap1.log Snap2.log -f:result.txt
2.2 批处理方式
env.bat
@echo off
SET APP_NAME=main.exe
SET APP_PDB_PATH=D:\MemoryLeakTest\build
@REM SET SYSTEM_PDB_PATH=srv*c:\symbols*http://msdl.microsoft.com/download/symbols
SET WINDBG_PATH=C:\Program Files\Debugging Tools for Windows (x64)
SET PATH=%WINDBG_PATH%;%PATH%
SET _NT_SYMBOL_PATH=%APP_PDB_PATH%;%SYSTEM_PDB_PATH%
SET CURRENT_PWD=%~dp0
gflags -i %APP_NAME% +ust
start.bat
@echo off
call env.bat
umdh -pn:%APP_NAME% -f:%CURRENT_PWD%\Snap1.log
pause
end.bat
@echo off
call env.bat
umdh -pn:%APP_NAME% -f:%CURRENT_PWD%\Snap2.log
umdh -d %CURRENT_PWD%\Snap1.log %CURRENT_PWD%\Snap2.log -f:%CURRENT_PWD%\result.txt
pause
3. 结果分析
main.cpp第8行有内存泄漏
// Debug library initialized ...
DBGHELP: main - private symbols & lines
.\main.pdb
DBGHELP: ntdll - export symbols
DBGHELP: KERNEL32 - export symbols
DBGHELP: KERNELBASE - export symbols
DBGHELP: VCRUNTIME140D - export symbols
DBGHELP: ucrtbased - export symbols
//
// 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).
//
+ 1076 ( 1076 - 0) 1 allocs BackTraceE2CEAC2E
+ 1 ( 1 - 0) BackTraceE2CEAC2E allocations
ntdll!RtlWalkHeap+00000213
ntdll!RtlAllocateHeap+00000AEB
ucrtbased!calloc_base+00001226
ucrtbased!calloc_base+00000FCD
ucrtbased!malloc_dbg+0000002F
ucrtbased!malloc+0000001E
main!operator new+00000013 (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp, 35)
main!operator new[]+00000013 (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\heap\new_array.cpp, 29)
main!main+00000038 (d:\MemoryLeakTest\main.cpp, 8)
main!invoke_main+00000034 (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl, 79)
main!__scrt_common_main_seh+0000012E (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl, 288)
main!__scrt_common_main+0000000E (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl, 331)
main!mainCRTStartup+00000009 (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp, 17)
KERNEL32!BaseThreadInitThunk+00000014
ntdll!RtlUserThreadStart+00000021
Total increase == 1076 requested + 44 overhead = 1120
4. 测试程序
main.exe
注意:因为windbg为64位,所以需要将程序编译为64位程序
- main.cpp
#include <iostream>
int main()
{
while (true)
{
printf("Press Enter to Continue\n");
getchar();
char *s = new char[1024];
}
return 0;
}
- CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(main)
add_executable( ${PROJECT_NAME} main.cpp)
License
License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎
如需转载请标明出处:https://blog.csdn.net/itas109
技术交流:129518033
Reference: