Windbg下对NT堆异常内存的排查

什么是NT堆

在 Windows 平台上有一个非常底层的内存分配函数 VirtualAlloc,它会一次性分配 64k 整数倍的内存段,内部对象按4k的内存页对齐,如果让程序直接接触 VirtualAlloc,很容易造成内存的浪费以及分配效能的降低,为了提高性能和内存使用效率, Windows 给进程提供了一个堆管理器对对象分配进行细粒度化管理,32位程序的颗粒度位8Byete,64位程序则为16Byte。

Windows NT 堆有两种类型 进程堆、私有堆。进程堆是进程启动时,Windows 加载器都会给当前进程创建一个默认的进程堆 (ProcessHeap),生命周期等同于进程,且64位程序额外多一个64k的nt堆。

在Windbg中,NT堆相关的指令如下:

1)!heap -s 显示当前进程相关的堆概要信息

2)!heap xxxx  -m  显示包含指定堆的所有段条目

3)!heap  xxxxx  -h 显示包含指定堆的所有非 LFH 条目

4)!heap  xxxxx  -a  显示包含指定堆的所有信息

NT堆布局

注:

dt  ntdll!_HEAP xxx  显示特定堆的结构

HEAP 开头有一块大小为 0x4a8 的 HEAP_ENTRY  堆块,用来存放 _HEAP 结构的元数据信息。

NT堆数据结构表述

注:

1)Nt堆由Segment组成、而Segment则由若干Block组成

2) 分配对象如果小于512k 则放置于SegmentList中,大于512k中则存在于VirtualAllocdBlocks

3)dt ntdll!_HEAP_VIRTUAL_ALLOC_ENTRY xxx 显示特定虚拟分配块结构,继而查看到该虚拟分配块中实际分配块的地址,如下:

排查NT泄漏思路

由于c、c++没有GC对内存进行管理,所有不能直观查看对象的引用根。但是可以在操作系统层记录内存的分配栈记录,通过gflags /i xxxx.exe +ust 针对某一程序开启记录功能(实际上就是修改针对某程序的注册表配置)。gflags 是调试工具包附带的一个工具

1)首先执行!address -summary 确定内存泄漏处于nt堆中,如下

2) 其次执行!heap -s 查看NT堆的内存分配情况,如下 commit为SegmentList的占用情况(小于512的对象),

VirtBlocks为VirtualAllocdBlocks的占用情况

如果是处于SegmentList上,则通过 !heap -stat -h xxxx -grp S 进行分组分析

执行  !heap -flt s 424  根据大小查找对应的block,最后通过!heap -p -a xxxx 查找指定block的分配栈信息

3)如果是大于512k,则需要执行!heap -m xxxx 查看堆上的Virtual Alloc List,最后执行 !heap -p -a xxxx+0x18 即可查出分配该virtual block的代码

因为ntdll!_HEAP_VIRTUAL_ALLOC_ENTRY的结构体偏移位置+0x18 为BusBlock,因而要加+0x18(32位)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值