赞
踩
通过对malloc,free源码的分析,发现在堆上分配内存,很容易造成内存碎片。内存碎片在这里可以从两个方面进行分析,物理地址的内存碎片和线性地址(虚拟地址)的内存碎片。
首先是物理地址的内存碎片,malloc_free_list大小依次为8,16,32....。那么我们请求的大小加上4字节的额外开销,如果和malloc_free_list插槽的大小一致,就不会产生碎片,反之,就会。如请求大小为5,那么加上额外开销大小就为9,第一个插槽无法满足,只有第二个插槽满足,但是第二个插槽分配单位是16,那么就是只有9个字节的大小,也要占用一个16字节的单元,相应的产生了7个字节的内存碎片。对于小数据单元来说,因为每次请求内存,最小是一页,比如对于第一个插槽,就会产生4096/8个单元,但程序不一定会申请这么多小的内存块,相应的这也不能高效的利用物理内存。这里还有个问题,如果内存不断的申请,如连续分配了多个物理页面供一个插槽使用,那么当释放时,程序会把物理内存归还给系统吗?至少在free中,是没有做的,也做不到,它只是简单的把内存单元添加到malloc_free_list插槽中。关于物理页面释放的问题,只有通过内核代码,才能确定物理内存释放的机制,而每个程序虚拟内存是通过vm_area_struct来管理的。
其次是线性地址的内存碎片,对于32位系统来说,用户虚拟地址只有3G,除了程序代码段,数据段,栈...,留给堆的有效线性地址也是有限的。如果频繁的分配小的内存块,他就会占用小的页面,这样当程序释放内存时,就会产生许多小的不连续的线性地址,当程序需要连续大的线性地址时,就会产生麻烦。具体是怎么实现的,等查了内核代码就明白了。
通过以上分析,对于在堆上申请内存,是会产生一定代价的,特别是滥用,后果也是比较严重的。内存碎片是需要关注的问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。