从以下连续步骤中,我们可以了解到 alloc 工作时的基本流程。其中包含战备池、自由链表每次最多新增20个区块、追加量、碎片处理、内存不足时的处理等概念

起始

image.png

  • free_list 数组包含16个元素,子元素分别管理不同内存大小的自由链表(单链表)

第一次内存申请

  • 分配器的客户是容器,即分配器服务于容器
  • 使用 malloc 申请的内存大小可能不同,因此需要借助 cookie 记录大小信息以进行后续的内存释放动作
  • 容器的所有元素大小已知且一致,因此可以不使用 malloc(不使用 cookie )
  • 在 alloc 工作时,总是先把可用内存放到战备池,再从战备池切割适当的内存到 free_list 管理的链表

image.png

补充描述
  • 容器申请 32 bytes, 由于 pool(战备池)为空,故使用 malloc(包含 cookie) 索取内存并成功向 pool 加注 32 x 20 x 2 + RoundUp(0>>4) = 1280 bytes, 从中切出 1 个区块返回给容器, 19 个区块给 list#3, 剩余 640 bytes 备用(战备池)
  • 战备池:由 start_free、 end_free 指针描述
RoundUp (0>>4) : 追加量,会越来越大
RoundUp : 是一个函数,将一个数值调整到 8 的边界
0 >> 4 : 0(目前的申请总量,初次值 0) / 16

无文档可说明为什么需要使用追加量,且每次追加量值是累计申请量除以16,或许为经验值

第二次内存申请

image.png

补充描述
  • 圆滑连接线表示图中内存块在地址上连续
  • 直角连接线表示图中内存块在自由链表中连续

第三次内存申请

image.png

第四次内存申请

image.png

补充描述
  • 经过以上操作,代码中已经创建了 4 种容器,每个容器大小各不相同,由图中的 4 条链表进行分别管理
  • 总计使用两次 malloc

第五次内存申请

image.png

第六次内存申请

image.png

第六次内存申请

image.png

补充描述
  • 经过以上操作,代码中已经创建了 7 中容器,每个容器元素大小各不相同,由图中的 7 条链表进行分别管理
  • 总计使用三次 malloc
  • 特别说明,如果多种容器(vector、list、queue、deque)它们所管理的对象大小相同,此时会共用同一条子自由链表

第七次内存申请

image.png

第八次内存申请

image.png

第九次内存申请

image.png

第十次内存申请

image.png

补充描述
  • 图中 free_list[8] 和 free_list[9] 为虚线,表示空链表(指向 null),无可用内存块

    • free_list[9] 因为内存块被回填战备池以供给 alloc 使用
    • free_list[8] 因为唯一内存块被使用返给客户

第十一次内存申请

image.png

第十二次内存申请

image.png

产生的疑惑

image.png

补充描述
  • 检讨 1 技术难点:

    • 如何找到自由链表中合适大小且内存相邻的两个或多个节点进行合并
    • 不知道链表的长度,尤其内存块不断动态被申请又被回收
  • 检讨 2 后续讲解

TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧