在大型项目中,内存泄露并不会立即crash,会使系统性能不断下降,甚至因内存耗尽而崩溃。排查起来难度也比较大,申请内存的地方很多。这里介绍的这种方法可以迅速定位问题。
下面的程序crash64,每秒会申请1M的内存,而一直都没有释放,产生内存泄露
windbg 中有个小工具 UMDH可以追踪系统每个进程堆分配和释放的过程,通过分析比较能够对比出哪一次分配的堆空间没有释放。
gflags /i ImageName +ust
mageName表示进程名字
这里输入gflags /i crash64.exe +ust
通过设置环境变量_NT_SYMBOL_PATH,UMDH可以找对应的PDB符号文件
这里的符号文件包括两部分,
一是系统的,例如NTDLL,MSVCR100, kernel32等等
二是我们程序的
因此我配置的环境变量如下
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;D:\sample\crash64\x64\Release
这样配置就完成了 可以开始分析了
这时再次运行crash64.exe ,打开PE 找到PID 为4800
CMD中输入umdh -p:4800 -f:d:\crash64old.log
此时保存了一个日志文件到D盘
等一段时间 观察PE的内存趋势图,感觉发生了内存泄露后 我这个是每秒钟都会发生一次内存泄露 所以不用看PE了
再次输入 umdh -p:4800-f:d:\crash64new.log
d:\crash64old.log d:\crash64new.log 名字都是可以随便起的
又保存了一个日志到D盘
现在输入umdh -d d:\crash64old.logd:\crash64new.log > d:\crash64.txt
UMDH就开始比较这两个日志文件了 并将比较的结果存在crash64.txt中
注意这里的文件名需要是绝对路径 不然就定位到systerm32目录中去了上面我就搞错了次
这时打开crash64.txt
+ 234873856 ( 350213696 - 115339840) 334 allocs BackTrace75D00
+ 224 ( 334 - 110) BackTrace75D00 allocations
ntdll!?? ::FNODOBFM::`string'+0001913B
MSVCR100!malloc+0000005B
MSVCR100!operatornew+0000001F
crash64!wmain+00000036(d:\sample\crash64\crash64\crash64.cpp, 16)
crash64!__tmainCRTStartup+0000011A(f:\dd\vctools\crt_bld\self_64_amd64\crt\src\crtexe.c, 552)
kernel32!BaseThreadInitThunk+0000000D
ntdll!RtlUserThreadStart+0000001D
Total increase == 234873856 requested+ 7168 overhead = 234881024
结果出来拉
+224表示增加申请的次数
234873856 /224 = 1,048,544 = 1024 * 1023 跟代码中实际现象一样
(怎么不是1024 *1024 是1024*1023?)
申请的位置在crash64.cpp中的16行
正是 这句 p = newchar[1024 * 1024];