Windows堆管理器概述

在Windows下,堆管理器的原理如下图:
堆管理器

堆的空间布局

堆的空间布局

堆的创建

每个进程在创建时,加载器执行用户态的初始化函数,调用RtlCreateHeap函数为进程创建第一个堆,即默认堆。
应用程序也可调用HeapCreate创建 其它堆,且只能为本进程自己用,此堆为私有堆。
进程的进程环境块(PEB)存放当前进程的所有堆。

PEB结构体变量名 含义
ProcessHeap 进程默认堆句柄,即默认堆的起始地址
NumberOfHeaps 进程中堆的数量
MaximuNumberOfHeaps 进程堆数组的目前大小
ProcessHeaps 存放堆句柄的数组(起始地址,结束地址)

堆的清理

应用程序可不必销毁进程的默认堆和私有堆,系统在进程退出时会自动清理堆,而且是两次清理,调用的函数都是MmCleanProcessAddressSpace。
1.调用NtTerminateProcess或最后一个线程退出时。
2.系统工作线程删除进程对象时。

堆的管理函数

用户态的堆管理函数
NTDLL.dll
内核态的堆管理函数
NTOSKRNL.exe
功能
Ntdll!RtlAllocateHeap nt!RtlAllocateHeap 从堆上分配内存
Ntdll!RtlCreateHeap nt!RtlCreateHeap 创建堆
Ntdll!RtlDestroyHeap nt!RtlDestroyHeap 销毁堆
Ntdll!RtlFreeHeap nt!RtlFreeHeap 释放堆块
Ntdll!RtlSizeHeap nt!RtlSizeHeap 取堆大小
Ntdll!RtlZeroHeap nt!RtlZeroHeap 堆空间清零
Ntdll!RtlExtendHeap nt!RtlExtendHeap 扩展堆大小

堆块空间的释放

堆块空间可通过系统API实现,如malloc等。
堆块空间释放一般不是真正意义上的释放,只在以下条件才调用zWFreeVirtualMemory进行释放即归还系统。
1.本次堆释放的堆块大小超过了堆参数DeCommitFreeBlockThreshold(0x1000,4K)的阈值。
2.累计总空闲空间超过DeCommitTotalFreeThreshold(0x10000,64K)

堆的溢出检查

1.HVC(Heap Validation on Call)堆的调用时验证,即堆函数在每次调用时进行检查,一般默认关闭,因为影响速度。

2.HTC(heap tail check)堆尾检查,在堆块末尾增加8个字节(0xAB),可在堆释放时检查出堆溢出。

3.DPH(Debug Page Heap)调试的页堆(Win2000后引入)。主要是在可用数据前后加入只读页,当写入时触发异常。