1. 堆的申请

1.1 过程介绍

关于堆的描述,已经简单的在上面一篇文章中做过简单的介绍。具体可以参考 chunk 和 bins

下面我们来回溯下堆的申请过程

clipboard.png

clipboard.png

申请的顺序:

  1. 如果申请40B大小的chunk,首先去 fast bins 查看链表中是否有合适的,如果有直接返回地址。如果没有,进行下一步
  2. small chunk 里面查找是否有匹配的chunk,如果查找到,直接返回指针地址。 如果没有,进行下一步
  3. 在 unsorted bins 查找,如果没有找到,把 fast bins 里面的bins 放入 unsorted bins,进行合并,看看是否有满足的,进行切割或者重组,重新分配到 small bins 或者 large bins
  4. 如果申请的 > 512B,则去large bins 里面去查找。 如果找到进入下一步,大小类似的可以进行切换,比如有个 568b 的,切割 512b 返回指针供用户态使用,剩下的56b,重新放入到unsorted bins。等待下次申请的时候,再次重新分配。
  5. top chunk。 top chunk 通过移动brk,向内核空间申请
  6. 对于大于 128k,使用mmap 申请内存。(申请之后的free 会直接释放,返还给内核空间)

1.2 例子演示

示例:申请大小不同的内存块

clipboard.png

下图是:通过堆申请内存空间的时候,在heap中的形象表示。

clipboard.png

输出结果,打印地址

clipboard.png

前面三个是连续的(紧挨着的),后面一个相差比较大,是从 mmap 分配的

如果申请8K的不够用了,P6是从 P3后面重新申请的

2. 堆的释放

示例代码:

clipboard.png

clipboard.png

clipboard.png

可以看出 P5的地址和P1是一样的

根据结果倒推理论:

释放的 unsorted bins 对 32k 的进行切割,分给 24 k ,剩下的8k 放到自己上

再次申请6k的chunk

clipboard.png

P6 申请了6k,unsorted bins 的 8k 进行再分配

申请8k

如果申请了8k,就不行了 ,因为bins 的 chunk 有头部大小,所以不能简单的 24 + 8

需要从尾部重新分配地址空间

clipboard.png

3. 堆的合并

clipboard.png

地址是连续的

clipboard.png

过程推演

  1. 释放 32k ,会放到 unsorted bins
  2. 申请 12k,先从 fast bins 中查找,没有找到,然后去 small bins 没有。 然后去 unsorted bins ,有一个 32k的
    进行切割,12k 返回,剩下的20k 放到 unsorted bins
  3. 申请 80k k,先从 fast bins 中查找,没有找到,然后去 small bins 没有。 然后去 unsorted bins
    没有,然后就去把 small bins 的拿过来放到 unsorted bins ,合并 。 可进行84k 的切割,80k 的返回
    剩下的 4k 放到 unsorted bins

100. 致敬

如有不详,请参考王老师的精彩讲解 堆栈管理
学习过程中,获得了极大的满足感,把之前的一些东西串联了起来。十分感谢 王利涛老师
在此表示感谢。
PS:本文中所有的资源和图片均来自视频中
另外十分推荐一本书 深入理解计算机系统


天真真不知路漫漫
70 声望6 粉丝

1