堆(heap)系列_0x04:堆的内部结构(_HEAP=_HEAP_SEGMENT+_HEAP_ENTRY)

提示1:正常情况下,程序员是可以不用关心操作系统是怎么维护堆的;但是当堆被破坏,想要查找原因时,排查手段中gflags.exe启用相关堆调试支持的功能时,如果不理解堆的内部结构,估计会一脸懵逼…

提示2:查看堆的内部结构,最好会使用WinDbg,如果不会也没关系,下面我已经添加了查询结果的详细解释

说明:下面都是先给出结构体说明,后给出截图的方式;如果想深入研究页堆等更复杂的结构,一定要对堆的3种基础结构很了解才行

1.整体介绍

堆管理器通过Windows虚拟内存管理器来得到一块内存,这块内存被成为堆段(heap segment)

堆段的基本布局示意图

在这里插入图片描述

下面是一个堆段的使用顺序:

  • 1.堆段最初被创建时

其中大部分虚拟内存是被保留状态(reserve),只有低地址的一小部分是被提交的(commit)状态

  • 2.程序员申请内存

当堆管理器使用完已经提交的内存或不足以提供程序员所需内存,堆段将进一步提交(commit)一部分内存,然后对新的内存进行分割处理,将合适堆块给程序员使用

  • 3.堆段使用完所有空间

堆管理器将创建一个新的堆段(heap segment),默认创建新堆段大小是之前的2倍(详细要看算法);会用一个链表统一记录相关的堆段(heap segment

问题:堆管理器是否会释放某个堆段的内存?

不会,内存会始终保留,但是堆管理器可以取消内存提交(decommit

简要介绍一下每个堆都要有的3种数据结构,先看一下结构的层次关系

0:000> dt -r2 ntdll!_HEAP 00a30000					#00a30000为HeapCreate创建堆的句柄(指向堆管理结构的指针)
   +0x000 Segment          : _HEAP_SEGMENT			#描述段的信息,0号段的首地址
      +0x000 Entry            : _HEAP_ENTRY			#描述堆块的信息
#可以看到_HEAP包含_HEAP_SEGMENT和_HEAP_ENTRY,且3个结构的第一个描述的首地址相同

下面是WinDbg的截图

在这里插入图片描述

基本结论:每个堆至少拥有一个00号段(Segment),最多可拥有64个段;堆管理器在创建堆时会建立一个段,如果堆是可以增长的话,用完一个段后堆会自动增长;00号段开始处存放着一个HEAP结构的头部信息,每个段都有一个HEAP_SEGMENT结构来描述自己(在每个段的起始处)

2.HEAP结构

堆管理器使用HEAP结构记录和维护每个堆的管理信息,位于每个堆的开始处

HeapCreate返回的句柄是创建堆的起始地址,即也是指向HEAP结构的指针

#1.ntdll!_HEAP大小
0:000> ?? sizeof(ntdll!_HEAP)
unsigned int 0x258(on600)

#2.列出当前进程的所有堆
0:000> !heap -h
Index   Address  Name      Debugging options enabled
  1:   00a90000 												#句柄
    Segment at 00a90000 to 00b8f000 (00007
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值