堆是应用程序动态分配的内存区域。常用的做法是程序向操作系统申请一块适当大小的堆空间,然后由程序自己管理这块空间。
在Windows中,堆管理器(Heap Manager)提供了一套与堆相关的API,用来创建、分配、释放和销毁堆空间。
⦁ HeapCreate : 创建一个堆
⦁ HeapAlloc : 在一个堆里分配内存
⦁ HeapFree : 释放已经分配的内存
⦁ HeapDestory : 摧毁一个堆
堆分配算法管理一大块连续的内存空间,能够按照需求分配、释放。简单的堆分配算法有:空闲链表和位图等。
1 .空闲链表
把堆中各个空闲的块按链表的方式连接起来,当用户请求一块空间时,可以遍历整个链表,直到找到合适大小的块;当用户释放空间时,将它合并到空闲链表中。
图:空闲链表分配
空闲链表中,堆的每一个空闲空间的开头(或结尾)有一个头结构(header),头结构里记录了上一个(prev)和下一个(next)空闲块的地址,所有的空闲块形成了一个链表。空闲链表中,需要存储该空闲块的大小,一旦链表被破坏或者记录空闲块大小的字节被破坏,整个堆就无法正常工作。
2.位图
将整个堆划分为大量的块(block),每个块的大小相同,当用户请求内存时,总是分配整数个块的空间给用户。第一个块称为已分配区域的头(Head),其余称为已分配区域的主体(Body)。用一个整数数组来记录块的使用情况,每个块有头/主体/空闲三种状态,需要两位即可表示一个块,因此称为位图。
图:位图分配方式
这个堆分配了3片内存,分别有2/4/1个块,用虚线框标出,其对应的位图是(high)11 00 00 10 10 10 11 00 00 00 00 00 00 00 10 11(low) 。其中,11表示H(Head), 10表示主体(Body),00表示空闲(Free)。
位图的优点:
⦁ 速度快
⦁ 稳定性好
⦁ 块不需要额外信息,易于管理
位图的缺点:
⦁ 容易产生碎片
⦁ 如果堆很大,或者块很小,那么位图会很大。
实际应用中,堆的分配算法往往是多种算法复合而成。