• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2025-03-29 16:22 Aet 隐藏边栏 |   抢沙发  3 
文章评分 1 次,平均分 5.0

示例dump分析:堆内存泄露

代码

分析步骤一

  1. 在程序启动时,先用下面命令查看堆的情况
  2. !heap -s

  1. !heap -stat -h 1cb0000

分析步骤二

  1. g
    1. 让程序跑一会儿
  2. !heap -s
    1. 对比发现Commit多了128h

  1. !heap -stat -h 1cb0000

观察

  1. 对比数据发现:
    1. 新增高频块:3048 字节)占 10.92%,共 2610 个块,总占用 2400 字节
    2. 原最大块 1e5a 占比下降:从 33.87% 降至 8.71%,但块数量仍为 1
    3. 新增大块:12344660 字节,5.22%)、12004608 字节,5.17%
    4. 碎片化加剧:新增 1016 字节)、120288 字节)等高频小块,总块数达 2610 个(30 尺寸)
  2. 疑点:
    1. 1e5a 块:在两份数据中均存在且占用较高,可能是长期未释放的缓存或泄漏对象
    2. ed63798 字节):仅第二份出现,需验证是否为合理分配
    3. 7901936 字节):新增,第二份中占 4.34%,可能关联数组或结构体分配
    4. 6d21746 字节):非对齐尺寸,可能因自定义数据结构导致

验证一

  1. 查看1e5a

  1. 查看ed6

  1. 查看790

  1. 查看6d2

  1. 查看10

  1. 查看50

  1. 查看30

  1. 通过!heap -stat -h 1cb0000看到的很多地址经过详细查看后,并不是我的目标模块
  2. 这个时候准备使用别的方案

验证二

  1. 使用了UMDH,来查看快照

  1. begin.log

  1. end.log

  1. diff.log
    1. 从对比结果的大量数据中,使用aet_breakpad_test!operator new+或者aet_breakpad_test!operator new+13搜索
    2. 找到了16
    3. 挨个得查看,最后发现了自己模块中分配内存的一条,如下

验证三

  1. 从验证二里面,定位了目标块5c
  2. windbg里面再次验证

  1. 逐条查看
  2. 第三条内容如下:

总结

  1. 经过了验证二和验证三,可以确定是main函数52行这里的问题

其他总结

!heap -stat -h 1cb0000的排序

  1. 这些排序好像并没有升序的方法
  2. -grp G
    1. 表示 按全局标签(Global Tags) 对内存分配进行分类统计
    2. 全局标签是堆分配时附加的元数据,常用于标记内存用途(如线程池、缓存等)
    3. 通过 G 分组,可快速识别不同标签下的内存使用情况

  1. -grp A
    1. 按分配大小分组
    2. 统计不同内存块大小的分配情况(如 16B32B64B 等)
    3. 适用场景:分析内存碎片化问题或高频分配的小对象

  1. -grp B
    1. 按块数量分组
    2. 统计每个分配大小对应的内存块数量
    3. 适用场景:识别内存分配频率最高的尺寸类别

  1. -grp S
    1. 按总分配大小分组
    2. 统计每个分配大小对应的总内存占用
    3. 适用场景:定位内存消耗最大的尺寸类别

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享