博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]malloc的内存用free释放后为何系统回收不了
阅读量:4944 次
发布时间:2019-06-11

本文共 1212 字,大约阅读时间需要 4 分钟。

在学习第七章7.8节时关于存储器分配这一块的时候,有个疑问,malloc(当然包括calloc和realloc)申请内存时候是怎么样申请的,free的时候内存是直接还给操作系统么?这个也是我在阿里面试时面试官所问的一道基础题。以下是摘自网友的解释,很详细。

 

    要解释这个问题首先要了解Linux进程使用内存的基本流程,进程的堆并不是直接建立在Linux的内核的内存分配策略上的,而是建立在glibc的堆管理策略上的(也就是glibc的动态内存分配策略上),堆的管理是由glibc进行的。 所以我们调用free对malloc得到的内存进行释放的时候,并不是直接释放给操作系统,而是还给了glibc的堆管理实体,而glibc会在把实际的物理内存归还给系统的策略上做一些优化,以便优化用户任务的动态内存分配过程。

 

glibc维护了不止一个不定长的内存块链表,而是好几个,每一个这种链表负责一个大小范围,这种做法有效减少了分配大内存时的遍历开销,类似于哈希的方式,将很大的范围的数据散列到有限的几个小的范围内而不是所有数据都放在一起,虽然最终还是要在小的范围内查找,但是最起码省去了很多的开销,如果只有一个不定长链表那么就要全部遍历,如果分成3个,就省去了2/3的开销,总之这个策略十分类似于散列。glibc另外的策略就是不止维护一类空闲链表,而是另外再维护一个缓冲链表和一个高速缓冲链表,在分配的时候首先在高速缓存中查找,失败之后再在空闲链表查找,如果找到的内存块比较大,那么将切割之后的剩余内存块插入到缓存链表,如果空闲链表查找失败那么就往缓存链表中查找,这么查找有什么依据吗?实际上是有的,正是这个方式让glibc有了自己的策略。
 
  在free的时候如果能合并在堆顶,也就是能和堆顶的空闲元素合并,那么就合并,因为堆的缩减仅仅在堆顶的空闲元素达到一定量的时候才会进行,因此为了尽快将内存归还操作系统,尽量优先考虑堆顶的释放,但是如果不能合并,比如它和堆顶根本就没有相邻,那么如果该释放的块大小小于80字节,那么就直接将之挂在高速缓存中,为了防止别的块和它合并所以并不更改使用位,这里可以看到,glibc实际上为小于80字节的小内存块维护了一个高速的内存池,如果有小块内存需求,直接从此池中拿走一个即可,只需要从高速缓存摘除之并不需要修改使用位,因为高速缓存中的元素的使用位均为1,这个高速缓存在有大内存块分配需求并且几个分配策略都失败的时候会被回收,回收进空闲链表的过程涉及到相邻块的合并,合并之后就有可能满足稍微大一些的内存分配需求,这里为何将界限定位为80个字节呢?实际上是一个经验值,那么介于80字节和128k字节之间的内存块在释放的时候要将使用位设置为0,然后试图和相邻块合并,然后挂入缓存链表。
 
原文:

转载于:https://www.cnblogs.com/wintersweetwang/p/4380905.html

你可能感兴趣的文章
利用ab压力工具对服务器进行压力测试
查看>>
SqlHelper
查看>>
P2物理引擎中文文档
查看>>
"CSRF token missing or incorrect."的解决方法.
查看>>
Android 使用MediaMetadataRetriever类获取视频第一帧及用法
查看>>
mvn常用命令
查看>>
从PowerDesigner概念设计模型(CDM)中的3种实体关系说起
查看>>
VMware Workstation 不可恢复错误: (vcpu-0)
查看>>
frontEnd(前端基础)
查看>>
2016 提高组c++ 错题
查看>>
网站通信协议升级到HTTPS&HTTP2
查看>>
猴子吃桃问题
查看>>
使用Win7+IIS7发布网站或服务步骤
查看>>
MVC公司架构介绍-框架分层
查看>>
python外部调用程序
查看>>
《JavaScript高级程序设计》读书笔记(三)基本概念第三小节 String、Object类型...
查看>>
Hyper-v 中 CentOS 连接外网之有线网卡
查看>>
JS字符串与汉字的字节获取
查看>>
函数的渐近增长表3
查看>>
DLL技术应用04 - 零基础入门学习Delphi47
查看>>