小木发现线上的程序通过任务管理器发现内存不断的增长,怀疑是不是内存泄漏呢?用户态内存泄漏可能是句柄泄漏堆内存泄露Socket, GDI对象等等。而对于C++程序员来说,碰到最多的无疑是堆内存泄露:也就是通过malloc或者new从堆上申请的内存,使用完成后,并没有释放,导致程序使用的内存越来越多。

小木找到了一个分析利器UMDH: 这也是Windbg工具集中的其中一个利器,它可以在一个时间点记录程序的当前程序使用的堆内存申请的信息,过一段时间后再记录一次程序使用的堆内存申请的信息,然后比较两次的结果来找到这段时间内增加的堆内存及其关联的函数调用栈,从而查找内存泄露。为了分析问题,小木先尝试着写了以下测试程序, 熟悉下工具的使用。程序每隔十秒钟调用一次MemorLeakFunction ,在函数中每次会从堆上申请一段内存空间,并且没有释放。

#include <iostream>
#include <chrono>
#include <thread>void MemoryLeakFunction()
{const int STR_SIZE = 100;char * pStr = new char [STR_SIZE];strcpy_s(pStr, STR_SIZE, "Memory Leak Sample");std::cout << pStr << std::endl;
}int main()
{while (true){MemoryLeakFunction();std::this_thread::sleep_for(std::chrono::seconds(10));}return 0;
}

第一步小木先使用gflag(这个也是Windbg工具集中的一个重要工具,主要用于修改系统的配置来达到调试的目的)。以下命令可以对MemoryLeak.exe程序申请堆上内存的时候记录其函数调用栈。
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags" -i MemoryLeak.exe +ust。直接运行gflags图形化界面打开如下图, 开启Create user mode stack trace database

第二步 运行测试程序MemoryLeak.exe

第三步 将你程序的symbol文件MemoryLeak.pdb拷贝到mysymbols目录下。运行命令配置Symbol:Set _NT_SYMBOL_PATH=C:\mysymbols;SRV*C:\symbols*http://msdl.microsoft.com/download/symbols

第四步 保存当前程序申请内存的记录,相当于做一个堆内存申请的Snapshot,并且将结果导入到C:\umdhlog\begin.log。运行命令(需要一些时间,请耐心等待哦)"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:MemoryLeak.exe -f:C:\umdhlog\begin.log

第五步 等程序运行一段时间后。这个等待的时间根据程序内存泄露的快慢来自行决定,要有足够的时间,来表现出程序使用堆上内存的差异。假设这里等待5分钟左右,再次运行如下命令,将结果导入到C:\undhlog\end.log中: "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:MemoryLeak.exe -f:C:\umdhlog\end.log

第六步 最后一步来比较end.logbegin.log内存申请的差异,来找到这段时间内增加的堆内存请求调用栈,并且导入到c:\umdhlog\diff.log。运行命令(有时候运行比较长,可以利用这段时间思考下人生吧):"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" C:\umdhlog\begin.log C:\umdhlog\end.log -f:c:\umdhlog\diff.log

最后一步 diff.log中可以看到增加的内存申请的函数调用栈,比如这段

+    1194 (  157c -   3e8)     37 allocs    BackTrace1
+      2d (    37 -     a) BackTrace1  allocationsntdll!RtlpAllocateHeap+2122ntdll!RtlpAllocateHeapInternal+5E5ucrtbase!_malloc_base+36MemoryLeak!operator new+1F (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp, 35)MemoryLeak!main+2D (c:\personal\git\beyourbest\cpp\windbgsample\memoryleak\memoryleaksample.cpp, 17)MemoryLeak!__scrt_common_main_seh+10C (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl, 288)KERNEL32!BaseThreadInitThunk+14ntdll!RtlUserThreadStart+21

注意里面默认采用的是16进制表示的数量,比如0x1194表示在umdh比较的两个时间段之间,这段函数调用栈申请了4500个字节的堆空间,0x2d表示这之间调用了45次。 最关键的部分就是函数调用栈了,里面指明了在memoryleaksample.cpp文件的第17行进行了内存申请。这个时候我们一般对这段代码进行审查,都能够找出内存泄露的原因,比如这里的例子,使用后未释放内存。

小木在熟悉了UMDH的使用后,对线上出现的实际问题进行分析,也很快找到了内存泄露原因。


最后是个人微信公众号,文章CSDN和微信公众号都会发,欢迎一起讨论。

Windows程序内存泄漏(Memory Leak)分析之UMDH相关推荐

  1. Windows程序内存泄漏(Memory Leak)分析之Windbg

    一.背景 近期有一个项目在运行当中出现一些问题,程序顺利启动,但是观察一阵子后发现内存使用总量在很缓慢地升高, 虽然偶尔还会往下降一些,但是总体还是不断上升:内存运行6个小时候从33M上升到80M: ...

  2. Pytorch内存泄漏Memory Leak

    文章目录 1. 问题描述 2. 问题排查 3. 参考 1. 问题描述 在运行程序是,通过要进行压力测试,在程序的各项性能稳定时才可以进行上线,其中主要的性能指标包含cup,内存,显存,这里遇到的问题就 ...

  3. Android 内存管理 Memory Leak OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  4. android内存溢出和内存泄漏的区别,Android 内存溢出和内存泄漏以及Leak Canary的使用...

    一.内存泄漏和内存溢出的区别 内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才 ...

  5. Linux 下几款程序内存泄漏检查工具

    Linux 下几款程序内存泄漏检查工具 chenyoubing | 发布于 2016-07-23 10:08:09 | 阅读量 93 | 无 写这篇博客的原因呢是因为自己在编写基于Nginx磁盘缓存管 ...

  6. SQL Server 内存泄露(memory leak)——游标导致的内存问题

    原文:SQL Server 内存泄露(memory leak)--游标导致的内存问题 转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql ...

  7. java程序内存泄漏场景及预防

    为什么80%的码农都做不了架构师?>>>    虽然jvm有垃圾回收机制,如果程序编写不注意某些特定规则,仍然会导致java程序内存泄漏,最终可能出现OutOfMemory异常. 1 ...

  8. 关于Android应用程序内存泄漏 你需要知道的一切

    关于Android应用程序内存泄漏 你需要知道的一切 原文:https://blog.aritraroy.in/everything-you-need-to-know-about-memory-lea ...

  9. 性能优化之内存泄露(Memory Leak)常用分析工具(另3种)

    1 LeakCanary(最常用,能监控整个App内存泄漏情况) 1.1 使用LeakCanary // 仅在debug包启用LeakCanary debugImplementation 'com.s ...

最新文章

  1. 为什么打印还要另存为_锦学考研 | 打印准考证的常犯错误
  2. 如何设置运行在Virtualbox内的Ubuntu虚拟机的静态ip地址
  3. Strategy(策略)--对象行为型模式
  4. JBoss Drools –入门
  5. vue和jquery的交互问题,何时用jquery何时用vue
  6. Nexus私服下载及安装
  7. 主流NoSQL数据库评测之HandlerSocket
  8. MIUI小米主题和迪士尼中国达成授权合作 推出专属定制主题
  9. 系统集成项目管理师 高项论文 项目进度管理
  10. 重新安装OFFICE2010失败
  11. Nano板使用USB与PX4通信
  12. 在 Vue 中使用lodash对事件进行防抖和节流
  13. vue博客模板—Gblog
  14. 笔记本手机都能用的充电器,做的只有乒乓球大小,AOHi 65W氮化镓充电器体验
  15. 基于matlab的运动目标检测,基于matlab的运动目标检测.doc
  16. MyEclipse2014用外部的浏览器运行web项目
  17. 百度网盘网页倍速播放视频的小技巧
  18. Halcon入门(1)——选取ROI区域
  19. 《西游记》中真假美猴王的分析
  20. Arduino单片机(五).基于OpenWrt模块的无线视频遥控小车设计

热门文章

  1. 获取 RRD 文件的信息
  2. egg extend ts_NAS初体验—威联通TS-451D - jingkunliu
  3. 二、Docker配置阿里镜像加速器
  4. 【oracle报错】ORA-01722:无效数字
  5. 编解码学习笔记(七) 微软Windows Media系列
  6. Qt程序移植到ARM
  7. 比Navicat好用百倍的通用数据库管理工具,功能强大,最主要还免费!
  8. IOT语义互操作性之语义
  9. PS 基础知识 .atn文件如何使用
  10. 迪文串口屏(DMG10600C101-03WTC)的通讯测试