Windows Via C/C++ 读书笔记 12
Heap(堆)
1. Overview
堆是除了Reserve-Commit和Memory-Mapped Files外的第三种也是最后一种内存管理方式。它适合用来保存数量很多的小块,优点是不需要做复杂的reserve-commit操作,缺点是不能commit-decommit最大化利用内存。
堆实际上是在进程地址空间中reserve出来的一个地址空间。堆中大部分地址空间是没有commit的(未分配实际内存,见前面章节),当程序在堆上面allocate内存的时候,堆管理器会完成commit操作。用户不再直接reserve-commit,一切由系统代劳了。
2. 进程的默认堆(Default Heap)
进程在创建的时候就创建了一个堆,叫做默认堆(Default Heap)。操作系统会在系统函数中使用到这个堆。因为它在进程执行前被创建,进程结束后自动释放,因此用户不能对它做创建和释放操作。系统保证对default heap的访问是串行的,即同一时间只有一个线程在它上面分配或释放内存。
如果想获取进程的默认堆句柄,调用:
HANDLE GetProcessHeap();
3. 堆的使用目的
主要有这么几个:
1. 访问安全性,把相同的东西放在同一个堆,其它线程或者函数根本不会使用到这个堆,因此不会因为指针错误影响到这个堆得数据。
2. 提高访问速度。把数组、链表节点、二叉树节点之类需要一次访问多个内存块的数据放在同一个堆中,使它们能保存在相同的内存Page里面。那么访问的时候,可以减少跨Page访问,减少物理内存页面和Page File的交换动作。
3. 提高释放内存速度,不需要一个个释放对象,直接把整个heap都释放掉。
4. 避免线程同步,跟1其实是一码事,各个线程用自己的heap。这个目的其实很白痴,变量肯定被设计在线程自己的访问域,怎么会把自己的变量放到全局访问呢。
4. 创建额外的Heap
//创建Heap
HANDLE HeapCreate(
DWORD fdwOptions,
SIZE_T dwInitialSize,
SIZE_T dwMaximumSize);
//Alloc内存
PVOID HeapAlloc(
HANDLE hHeap,
DWORD fdwFlags,
SIZE_T dwBytes);
5. 小结
使用Heap可以方便的在连续的地址空间内分配和释放内存,减少Page交换和跨Page访问数据;缺点是不能精确控制内存的commit-decommite。适合需要大量创建小对象的场合。比如动态链表,树等。