zoukankan      html  css  js  c++  java
  • malloc内存分配与free内存释放的原理

      前段时间一直想看malloc的原理,在搜了好几篇malloc源码后遂放弃,晦涩难懂。

      后来室友买了本深入理解计算机系统的书,原来上面有讲malloc的原理,遂看了,先明白理论,在看代码就理解比较快了= =

      1.问题的引入:

       为什么要使用malloc,主要是因为在代码中,为了节约内存,很多数据都是动态生成的,所以会用malloc,对应于C++中的new,底层还是调用malloc.

      2.碎片的问题:

       会有内部碎片与外部碎片的问题,内部碎片难以消除(因为字对齐之类的问题),而外部碎片是可以消除的(如果不消除的话,外部的内存块越来越小,虽然数量多了,但是利用率会急剧下降!)

      3.需要解决的问题:

      

      4.隐式的空闲链表:

      一个简单的堆块,这里只有头部,下面为了优化,还会使用尾部。

      

      隐式的空闲链表:

      

      这样就把用链表的方法把堆空间给联系起来了。特点明显,实现简单,但分配时查询空堆块是线性时间的。

      5.放置以分配的块:

        1)、首次适配:从链表开始寻找适合的空堆块,直到找到为止

        2)、下一次适配:从上一次的分配点开始找,直到找到适合的空堆块为止

        3)、最佳适配:查询整个链表,找到最合适(浪费最小)的空堆块

      6.分割空闲块:

        当前的分配的空堆块比所需要的空间大很多的时候,如果不分割,就会照成内部碎片过大,利用率下降。

        当需要3个字节的空间时,首次适配找到了满足条件的第二个堆块,但堆块过大,所以分割成两个16字节的堆块。

        

      7.获取额外的堆存储器:

       当链表中不能满足申请要求的堆块空间的时候,1)通过合并相邻的堆块空间,形成单个尽量大的堆块空间 2)实在没有其他办法了,分配器通过sbrk函数向内核申请格外的堆空间,分配器将堆空间插入到链表中,然后提供给申请空间的块。

      8.合并

      

      如果,在如上的情况下,合并两个块,由于当前块不知道上一个块的情况,它要通过遍历整个链表才能知道上一个堆块的空间是否为空,这样将花费线性的时间来合并与当前相邻的空闲堆块。有个类似双向链表的方法(不过不是真正的双向链表,只是可以加一个信息量,直接就可以知道上一个堆块的情况)

      

      上一个堆块的情况就容易知道了,下面有四种情况:

      

      

      这样,堆块合并的问题就解决了。

    参考:深入理解计算机系统

  • 相关阅读:
    Leetcode Binary Tree Preorder Traversal
    Leetcode Minimum Depth of Binary Tree
    Leetcode 148. Sort List
    Leetcode 61. Rotate List
    Leetcode 86. Partition List
    Leetcode 21. Merge Two Sorted Lists
    Leetcode 143. Reorder List
    J2EE项目应用开发过程中的易错点
    JNDI初认识
    奔腾的代码
  • 原文地址:https://www.cnblogs.com/huhuuu/p/3456662.html
Copyright © 2011-2022 走看看