malloc size_alloc和malloc的区别

malloc size_alloc和malloc的区别C++内存管理(4):malloc的秘密这次我们深入了解malloc,malloc究竟分配多么大的空间,以及整个过程是如何进行的。malloc其实并没有想象中那么低效,在底层的设计中也是充满着精妙之处的。以下分解内容以VC6版本

C++内存管理(4):malloc的秘密   这次我们深入了解malloc,malloc究竟分配多么大的空间,以及整个过程是如何进行的。   malloc其实并没有想象中那么低效,在底层的设计中也是充满着精妙之处的。   以下分解内容以VC6版本为基础。   main()的准备工作   下图展示了调用main之前编译器都做了什么。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   按照从下往上的顺序,依次调用了1-7这些初始化程序准备函数。   在其中,又会有一些嵌套式的调用。我们可以看到在ioinit中调用了诸如malloc_dbg(),堆分配相关的初始化,以及非常重要的sbh相关函数。   SBH小区块管理   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   从heap_alloc_base()这段代码中就可以看出,在申请空间小于1016时会调用_sbh_alloc_block(),而其他空间大小则会直接使用系统的HeapAlloc   这里的sbh代表Small Block Heap,是对于申请堆区小空间的管理方式。   而这部分内容在VC10时,这些管理方式被包装到了OS里面。   SBH就是我们要分析的重点。   SBH之始   在开始时,系统会先建立一个_crtheap,初值为4096。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   然后调用_sbh_heap_init(),分配配置SBH所需的管理空间。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   可以看到这里分配了16个HEADER,类似链表的结构。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   而之后动态配置中申请的空间就要与1016比较了,小于就从SBH取,大于就调用HeapAlloc()从_crtheap取。   有点像内存池的设计。   Header的结构如下:   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   其中Hi和Lo共有64位。Commit有32位。   还有一个指针以及一个结构体指针,这些在后面都会用到。   malloc()的真相   ioinit()申请空间   接下来就会进行一系列的内存分配与管理了。   首先调用的是ioinit(),这里会申请一些信息文件,大小为32*8=256 也就是16进制的100h   然后进入到debug模式   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   malloc就会对其进行包装。(这些包装都是为了debug做准备的)   debug模式包装   接下来就会在这100h的空间上下功夫。   首先整个区块的大小分为以下几块:
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   包括_CrtMemBlockHeader的大小,申请空间的大小以及无人区的大小。   这里就是动态申请,所以可以用这里的blocksize选择分配空间的方式(SBH还是系统)
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   _CrtMemBlockHeader是什么呢?其实就是我们以前所说的malloc分配的debug header。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   但这次我们可以更清楚它是由什么组成的。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   对照结构体的定义可以看出:   1和2是前后指针,用于连接多个block。   3指向的是申请这块空间的程序地址(所在的文件)。   4是记录申请使用该内存空间所在文件的行号   5是申请空间的实际大小,这里就是100h   6表示当前内存块的类型。这里有宏定义:   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   对应此处的是CRT块,也就是系统申请的内存。   7代表操作操作流水号   8则是无人区,一共上下共8个,大小是0xfd   这样无人区可以把实际申请内存空间像栏杆一样保护住。如果有内存越界发生可以在debug下及时发现。   这里的前后指针实现的效果如下: 就是将各个块连接在一起。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   管理机制   在使用heap_alloc_base()申请空间时,如果符合小区块,那么会调用   sbh_alloc_block()   sbh_alloc_new_region()   sbh_alloc_new_group()   在sbh_alloc_block()里,会加入pad填充部分把大小调整至16的倍数,然后再加上下cookie(每个cookie大小为4字节)   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   这里的cookie记录总的大小,注意是131h而不是130h,这是因为16进制结尾都是0,如果某块分给了客户端,就用1代表分配出去了。   sbh_alloc_new_region()则实现了管理空间,真正开始分配。   管理中心   region,是内存的管理中心。   前面我们说过有16个HEADERS,而每一个HEADER都管理着这样一个空间。   先来看结构体:   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   region有一个char类型的数组,64位。最重要的是bitvGroupHi和bitvGroupLow,一共有32组,每组都是64位的。   还有一个tagGroup结构体,用来管理32个group   这个结构体如下:   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   除了有一个用于计数的cntEntires,还有64个tagListHead   tagListHead其实就是一个双向链表结构   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   所以这64个相当于32组。   最后整体就是这样的结构:   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   总览全局   结合每一个Header和所有申请的内存,我们可以得到这样的管理图。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   先来看右边的一列,这是Header管理的空间但是是虚拟内存空间,只有当真正申请时才会真正分配。   而这些空间的总大小为1MB,共有32块,那么每块为32k   这32k会被分为8个page,每个page大小4k   然后将其首尾相接,交给管理中心。注意位置是在group0的最后一对前后指针。   这里管理大于1k的内容。因为1024k/16=64,刚好对应group的64个位置。所以大于1024的内容都交给最后一块管理。   这8个page也不是直接将4k串连起来,而是进行了一点处理。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   每个部分为4096bytes,先分出两个边界(黄色部分),是2*4=8bytes,剩余4088,调整到16的倍数,为4080,剩余的8作为保留。   这里的黄色部分为回收做了准备。   而分配的空间,就来自于这些切割好的空白部分。   比如前面ioinit申请的30h的空间,就可以从这里分出去。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   100h的实际申请空间+24h的debug header再加上两个cookies,总大小130h,这时对于进行debug header构造的程序来说,得到的地址就是这块空间的起始地址007d0ed0   内存分配流程   根据几张图,类似alloc那样来进行分配,看看发生了什么。   ioinit申请100h大小,区块大小130h,查找18号链表,发现无空闲。   先保留1MB的地址空间(没有分配),再实际分配32k的大小,分成8个page,再从page中分130h的空间。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   对于一个page来说,还剩余ec0的空间。   管理中心是如何记录这些变化的呢?   首先,group0的cntEntries会+1,说明有一块空间被分配了出去。   然后,header中的32组64bytes的数据结构可以记录对应的链表信息。   比如这时只有最后一条链表连有数据块,所以对应的group0的最后一位置为1
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   继续申请240h的空间大小,由page分配,剩余c80   group0的cntEntries继续+1变为2,有两块空间被分配。   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   假设已经经历了14次分配,此时对应的cntEntries也变为了14   这时有一块空间需要回收,大小是240h,那么应该还给240h/10h=36-1=35号链表。于是就把这块空间的前后指针拉向#35。cntEntries-1 变为13   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   同时管理中心改变group0对应的值   
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   表示第35号有连接数据块。   这里的前后指针依旧是嵌入式指针,在分配出去的时候是完整的空间,在回收时才会把前面的空间当作指针使用。   再申请b0的空间,按顺序检查链表,发现最近的有空间的链表是#35,所以从35号的空间中分出b0,剩余190。   cntEntries+1变为14   重新调整,把190h分给190h/10h=25-1=#24号链表。
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   同时修改管理中心的信息。
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   在经历了n次分配后,可能已经跳到了group1,管理中心对应的数据逐渐增加调整。
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   空间回收   malloc与free对应,而free并不是像alloc一样把区块据为己有,而是做到了真正的回收。   这时就用到了上下cookie。   cookie用来记录大小,但为什么要一对呢?因为当某一块为空时,直接根据其上下cookie就可以把上方和下方与之相连的空闲块都一次性回收。
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   free(p)在寻找区块时经历了以下过程: 首先看p在哪一个header中,再看p在哪一个group中,再看p在哪一个list中(看cookie)   这样的分段管理是非常利于归还内存的。   全回收   如何判断给出了几块空间,还有几块空间没收回?   还记得在group里有一个变量cntEntries,它可以记录有几块空间被分配了出去。   如果该值为0,那么说明空间已经全回收了。   但最后一块链表连接的8个page暂时不收回。为了预防下次再有申请内存的行为。直到出现两个全回收的group后,才会真正把所有空间归还。   实现方式是用_sbh_pHeaderDefer指针指向全回收的group所属的header,但暂时不释放,当第二个全回收group出现的时候去检查该指针的状态,如果为Defer那么就可以释放了。   malloc与allocator   我们知道了malloc的实现方式,那么与之前说的alloc这种设计有什么关联呢?
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   对于alloc来说,管理的区块最大是128bytes,而这么大的区块对于malloc来说就是SBH所管理的小区块。   malloc已经足够快了,单独设计并不是想要提升效率,而是为了减少cookie。   那一层一层的设计是否有些多余呢?
malloc size_alloc和malloc的区别
malloc size_alloc和malloc的区别   既然下层已经有这么精妙的设计,上层还有必要重新设计么?   当然是有的,抛开新的管理方式不谈,上层无法预测自己的使用场景,也就无法预测下层是否做了相应的管理,所以还是有必要的。   以上就是malloc的设计,可以说非常精妙了。

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/29123.html

(0)
上一篇 2024年 9月 12日
下一篇 2024年 9月 12日

相关推荐

关注微信