在《内存泄漏分析的利器——gperftools的Heap Checker》一文中,我们介绍了如何使用gperftools分析内存泄漏。本文将介绍其另一个强大的工具——Heap Profiler去分析堆的变化过程。(转载请指明出于breaksoftware的csdn博客)

我们使用类似于《堆状态分析的利器——valgraind的DHAT》中的测试代码作为例子。为了让Heap Profiler产生多份快照文件,我将申请的内存放大了很多

#include <stdlib.h>void* create(unsigned int size) {return malloc(size);
}void create_destory(unsigned int size) {void *p = create(size);free(p);
}int main(void) {const int loop = 4;char* a[loop];unsigned int mega = 1024 * 1024;for (int i = 0; i < loop; i++) {const unsigned int create_size = 1024 * mega;create(create_size);const unsigned int malloc_size = 1024 * mega;a[i] = (char*)malloc(malloc_size);const unsigned int create_destory_size = mega;create_destory(create_destory_size);}for (int i = 0; i < loop; i++) {free(a[i]);}return 0;
}

第19行每次申请1G的空间,且在整个程序周期中,都不会释放。

第22行每次申请1G的空间,每个空间都将在第29行释放掉。

第25行调用的create_destory方法,每次申请1M的空间,每次申请完就释放掉。

为了方便起见,我们还是要链接tcmalloc库,并开启调试信息

g++ heap_profiler.cpp -ltcmalloc -g -o heap_profiler

编译完后,使用如下指令开始分析。其中HEAPPROFILE表示的“生成快照文件的目录格式”。

HEAPPROFILE=/tmp/profile /home/fangliang/gperftools_test/heap_profiler/heap_profiler

会得到输出结果

Starting tracking the heap
Dumping heap profile to /tmp/profile.0001.heap (1024 MB allocated cumulatively, 1024 MB currently in use)
Dumping heap profile to /tmp/profile.0002.heap (2048 MB allocated cumulatively, 2048 MB currently in use)
Dumping heap profile to /tmp/profile.0003.heap (3073 MB allocated cumulatively, 3072 MB currently in use)
Dumping heap profile to /tmp/profile.0004.heap (4097 MB allocated cumulatively, 4096 MB currently in use)
Dumping heap profile to /tmp/profile.0005.heap (5122 MB allocated cumulatively, 5120 MB currently in use)
Dumping heap profile to /tmp/profile.0006.heap (6146 MB allocated cumulatively, 6144 MB currently in use)
Dumping heap profile to /tmp/profile.0007.heap (7171 MB allocated cumulatively, 7168 MB currently in use)
Dumping heap profile to /tmp/profile.0008.heap (8195 MB allocated cumulatively, 8192 MB currently in use)
Dumping heap profile to /tmp/profile.0009.heap (Exiting, 4096 MB in use)

第2到9行显示,每个快照都会增长1G的内存申请。第10行显示,释放了4G的内存,最终还有4G的内存没有被释放。这个分析结果和代码的逻辑是一致的:

第19行和第22行每次都申请1G空间,一共执行了4次,故8G的在用内存使用量。

第25行每次申请并释放了1M,故不会造成内存增长。

第29行每次释放1G的空间,共执行4次,释放了4G空间。最终有4G的内存泄漏。

我们先看下第一个快照的状态

pprof --text heap_profiler /tmp/profile.0001.heap

此时我们使用的文本输出方式(--text)

Using local file heap_profiler.
Using local file /tmp/profile.0001.heap.
Total: 1024.0 MB1024.0 100.0% 100.0%   1024.0 100.0% create0.0   0.0% 100.0%   1024.0 100.0% __libc_start_main0.0   0.0% 100.0%   1024.0 100.0% _start0.0   0.0% 100.0%   1024.0 100.0% main

第4到7行是调用堆栈,这段显示create方法申请了1G的空间,且该空间还是可用状态。

再查看快照2

pprof --text heap_profiler /tmp/profile.0002.heap 

其结果显示main函数和create函数各申请了1G的空间(第4~5行第1列),各占总未释放内存(2G)的50%(第4~5行第2列)。main函数中调用了create方法(第4~5行第3,4,5列显示出main中直接调用了create,因为main函数中直接和间接申请了2G的空间,其中1G是直接申请的)

Using local file heap_profiler.
Using local file /tmp/profile.0002.heap.
Total: 2048.0 MB1024.0  50.0%  50.0%   1024.0  50.0% create1024.0  50.0% 100.0%   2048.0 100.0% main0.0   0.0% 100.0%   2048.0 100.0% __libc_start_main0.0   0.0% 100.0%   2048.0 100.0% _start

为了更方便解读这组信息,我们使用图形显示命令

pprof --gv heap_profiler /tmp/profile.0002.heap 

显示结果如下

上图中,main下面“1024.0(50.0%)”意思是main函数直接申请了1024M尚未释放的空间,占总未释放空间的50%。再下面一行“of 2048.0 (100.0%)”意思是main函数直接或者间接申请了2048M尚未释放的空间(这意味着它申请并释放了的空间不在该统计内)。create中的信息解读是类似的。

如果只是单纯的看一个快照点,是比较难以发现问题。我们需要对比两个快照,比如我们对比1号和2号快照,看看1G内存的增长是什么导致的

pprof --gv heap_profiler --base=/tmp/profile.0001.heap  /tmp/profile.0002.heap 

可以发现,快照1和快照2的变化是:main函数自身申请了1G的空间。

我们再对比下8和9号快照

pprof --gv heap_profiler --base=/tmp/profile.0008.heap  /tmp/profile.0009.heap 

上面显示:main函数内部释放了4G的空间(出现了负值)。这个就是第29行代码的执行结果,分析和代码逻辑一致。

最后我们再看下最后一片快照

pprof --gv heap_profiler /tmp/profile.0009.heap

create函数导致的4G内存泄漏就一目了然了。

最后提一句,如果项目不能链接tcmalloc,则可以使用如下的指令去获取快照

LD_PRELOAD="/usr/local/lib/libtcmalloc.so" HEAPPROFILE=/tmp/profile /home/fangliang/gperftools_test/heap_profiler/heap_profiler

堆状态分析的利器——gperftools的Heap Profiler相关推荐

  1. 动态执行流程分析和性能瓶颈分析的利器——gperftools的Cpu Profiler

    在<动态执行流程分析和性能瓶颈分析的利器--valgrind的callgrind>中,我们领略了valgrind对流程和性能瓶颈分析的强大能力.本文将介绍拥有相似能力的gperftools ...

  2. 堆状态分析的利器——valgrind的DHAT

    在<堆问题分析的利器--valgrind的massif>一文中,我们介绍了如何使用massif查看和分析堆分配/释放的问题.但是除了申请和释放,堆空间还有其他问题,比如堆空间的使用率.使用 ...

  3. Google Heap Profiler使用方法

    最近在查找内存泄露的问题,使用了一些工具来查找问题,定位问题,但是工具都有各自的优劣,在我们实际的使用过程当中,只有各种工具结合使用才能发挥最大的效用. 由于项目需要,最近也开始使用Google He ...

  4. L2-012. 关于堆的判断(STL中heap)

    L2-012. 关于堆的判断 将一系列给定数字顺序插入一个初始为空的小顶堆H[].随后判断一系列相关命题是否为真.命题分下列几种: "x is the root":x是根结点: & ...

  5. 内存泄漏的定位与排查:Heap Profiling 原理解析

    系统长时间运行之后,可用内存越来越少,甚至导致了某些服务失败,这就是典型的内存泄漏问题.这类问题通常难以预测,也很难通过静态代码梳理的方式定位.Heap Profiling 就是帮助我们解决此类问题的 ...

  6. createbitmap导致的内存泄漏如何处理_C++ 如何避免内存泄漏,一篇就够

    前言 近年来,讨论 C++ 的人越来越少了,一方面是由于像 Python,Go 等优秀的语言的流行,另一方面,大家也越来越明白一个道理,并不是所有的场景都必须使用 C++ 进行开发.Python 可以 ...

  7. html5 自带video内存泄露_C++ 如何避免内存泄露?

    来源:知乎-张凯(Kyle Zhang) [CPP开发者导读]:内存泄漏是C/C++的一个老生常谈的问题,无论是新手还是有经验的开发者都会在这个问题上栽跟头. 本文向读者介绍了如何避免内存泄漏的方法和 ...

  8. 堆(heap)系列_0x0A:3种方法一次性解决堆溢出问题

    概述:本篇文章主要介绍堆问题中最常见的堆溢出问题的排查思路:常规思路 + 页堆思路 + 应用程序验证器思路 前提:可以看到懂得DPH(点击查看)和会使用应用程序验证器(点击查看)和WinDbg 文章目 ...

  9. c语言建立小根堆的算法,小根堆(Heap)的详细实现

    堆的介绍 Heap是一种数据结构具有以下的特点: 1)完全二叉树 2)heap中存储的值是偏序 Min-heap: 父节点的值小于或等于子节点的值 Max-heap: 父节点的值大于或等于子节点的值 ...

最新文章

  1. Linux的文件管理命令
  2. 如何右对齐弹性项目?
  3. Deco 智能代码体验版正式上线啦,快来体验设计稿一键生成代码~
  4. 办学10年,进入全国前10名!这所神奇的高校,迎来10岁生日
  5. gets函数没有输入会怎样_如果没有“227事件”,肖战的未来会是怎样的?
  6. 网络蜘蛛爬取邮箱地址
  7. NMF(非负矩阵分解)
  8. 行为树 中断的理解
  9. android应用的关闭自动更新,软件自动更新怎么关闭 安卓关闭软件自动更新
  10. 黑帽SEO常用作弊手法分析
  11. vue使用echarts图表渲染异常本地正常,线上时有时无的渲染
  12. 想要成为一名合格的数据分析师,需要学习哪些类型的书
  13. 【SSM - SpringMVC篇】03 - SpringMVC的参数绑定 - 参数自动绑定 - javabean对象参数绑 - 嵌套bean参数绑定
  14. python从小白到大牛百度云盘_Python从小白到大牛
  15. 文明 计算机丢失,文明6提示“msvcp140.dll丢失”怎么解决-解决文明6提示“msvcp140.dll丢失”的方法 - 河东软件园...
  16. ARM基础教程 | ARM、Cortex-M与ARMv8-M什么关系?
  17. 项目管理中,如何对各种文件进行统一版本管理?
  18. 在iframe中写html,使用jQuery在iframe中获取HTML
  19. 简易扩音机设计1——麦克风篇
  20. adis16448与MPU6050 无人机飞行对比测试

热门文章

  1. Eigen(1):Matrix模板类
  2. PCL:官方程序 Region growing segmentation
  3. 用深度神经网络搭建马赛克神器,高清无码效果感人
  4. 【camera-radar】基于ROS的多传感器融合感知系统实现(雷达+相机)(3)
  5. OpenCV(基础补充)图像二值化
  6. 【神经网络】(15) Xception 代码复现,网络解析,附Tensorflow完整代码
  7. C++中的vector的用法
  8. php接收不到ajax请求参数,我是否需要在ajax请求和接收该请求的php之间编码/解码查询参数?...
  9. MathType6.9b安装及在Word2013中无法正常使用的解决方法
  10. python二级多少分过_python考级有几个级别