[C/C++] malloc内存分配与free内存释放原理
1.问题的引入:
为什么要使用malloc,主要是因为在代码中,为了节约内存,很多数据都是动态生成的,所以会用malloc,对应于C++中的new,底层还是调用malloc。
2.碎片的问题:
会有内部碎片与外部碎片的问题,内部碎片难以消除(因为字对齐之类的问题),而外部碎片是可以消除的(如果不消除的话,外部的内存块越来越小,虽然数量多了,但是利用率会急剧下降!)
3.需要解决的问题:

4.隐式的空闲链表:
一个简单的堆块,这里只有头部,下面为了优化,还会使用尾部。

隐式的空闲链表:

这样就把用链表的方法把堆空间给联系起来了。特点明显,实现简单,但分配时查询空堆块是线性时间的。
5.放置以分配的块:
1)、首次适配:从链表开始寻找适合的空堆块,直到找到为止
2)、下一次适配:从上一次的分配点开始找,直到找到适合的空堆块为止
3)、最佳适配:查询整个链表,找到最合适(浪费最小)的空堆块
6.分割空闲块:
当前的分配的空堆块比所需要的空间大很多的时候,如果不分割,就会照成内部碎片过大,利用率下降。
当需要3个字节的空间时,首次适配找到了满足条件的第二个堆块,但堆块过大,所以分割成两个16字节的堆块。

7.获取额外的堆存储器:
当链表中不能满足申请要求的堆块空间的时候,1)通过合并相邻的堆块空间,形成单个尽量大的堆块空间 2)实在没有其他办法了,分配器通过sbrk函数向内核申请格外的堆空间,分配器将堆空间插入到链表中,然后提供给申请空间的块。
8.合并
合并两个块,由于当前块不知道上一个块的情况,它要通过遍历整个链表才能知道上一个堆块的空间是否为空,这样将花费线性的时间来合并与当前相邻的空闲堆块。有个类似双向链表的方法(不过不是真正的双向链表,只是可以加一个信息量,直接就可以知道上一个堆块的情况)。


共有四种情况:


从而解决了堆块的合并问题。
总结:
malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿链表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
[C/C++] malloc内存分配与free内存释放原理的更多相关文章
- malloc内存分配与free内存释放的原理
malloc内存分配与free内存释放的原理 前段时间一直想看malloc的原理,在搜了好几篇malloc源码后遂放弃,晦涩难懂. 后来室友买了本深入理解计算机系统的书,原来上面有讲malloc的原理 ...
- SQL SERVER 内存分配及常见内存问题(2)——DMV查询
原文:SQL SERVER 内存分配及常见内存问题(2)--DMV查询 内存动态管理视图(DMV): 从sys.dm_os_memory_clerks开始. SELECT [type] , SUM(v ...
- SQL SERVER 内存分配及常见内存问题(1)——简介
原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解 ...
- rt-thread中动态内存分配之小内存管理模块方法的一点理解
@2019-01-18 [小记] rt-thread中动态内存分配之小内存管理模块方法的一点理解 > 内存初始化后的布局示意 lfree指向内存空闲区首地址 /** * @ingroup Sys ...
- 目录_Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)
1.Java直接内存与堆内存-MarchOn 2.Java内存映射文件-MarchOn 3.Java Unsafe的使用-MarchOn 简单总结: 1.内存映射文件 读文件时候一般要两次复制:从磁盘 ...
- (转)java内存分配分析/栈内存、堆内存
转自(http://blog.csdn.net/qh_java/article/details/9084091) java内存分配分析/栈内存.堆内存 java内存分配分析 本文将由浅入深详细介绍Ja ...
- C程序的内存分配及动态内存
1.程序内存的分配 一个由C/C++编译的程序占用的内存分为以下几个部分:1)栈区(stack) — 由编译器自动分配释放 , 存放为运行函数而分配的局部变量. 函数参数. 返回数据. 返回地址等. ...
- Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组
版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:什么是静态内存什么又是动态内存呢? 静态内存:是指在程序开始运行时由编译 ...
- SQL SERVER 内存分配及常见内存问题 简介
一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQ ...
- C++_类和动态内存分配1—动态内存和类
静态类成员 num_strings成员声明为静态存储类.静态类成员有一个特点:无论创建了多少对象,程序都只创建一个静态类变量副本.也就是说,类的所有对象共享一个静态成员.num_strings成员可以 ...
随机推荐
- 【TOJ 5065】最长连续子序列(前缀和)
Description 给定一系列非负整数,求最长的连续子序列,使其和是7的倍数. Input 第一行为正整数N(1<=N<=50000),接下来有N行,每行有一个非负整数,所有整数不大于 ...
- 构建高可靠hadoop集群之3- Quorum Journal Manager
在正式环境中,搭建高可靠(ha)的系统是必须的. 例如oralce的rac,apache集群,windows服务器集群 本文不再赘言ha的重要性. 本文主要是对 http://hadoop.apach ...
- TCP回话劫持原理和利用
由于 TCP 协议并没有对 TCP 的传输包进行身份验证,所以在我们知道一个 TCP 连接中的 seq 和 ack 的信息后就可以很容易的伪造传输包,假装任意一方与另一方进行通信,我们将这一过程称为 ...
- vue-cli中vuex IE兼容
vue2.0 兼容ie9及其以上 vue-cli中使用vuex的项目 在IE中会出现页面空白 控制台报错的情况:我们只需要安装一个插件,然后在main.js中全局引入即可 安装 npm install ...
- 百度app红包? 百度全家桶?果断卸载
听说今年的春晚红包与百度合作.这不 刚又下载了一个百度app,之前下载过,太卡了,用户体验极.本身对百度也没啥好感,再加上这周看了:百度已死的文章,搜索全百家号.具体啥情况,你们百度搜一搜吧
- 11 非阻塞套接字与IO多路复用(进阶)
1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建 ...
- 笔记-python-常见特殊变量
笔记-python-常见特殊变量 类似__xx,以双下划线开头的实例变量名,就变成了一个私有变量(private),只有内部可以访问,外部不能访问: 类似__xx__,以双下划线开头,并且以双下划线结 ...
- 激活Windows Server 2008R2
1. 用管理员身份运行mini-KMS_Activator_v1.053_ENG 2. 点击倒数第二个菜单Activation Windows VL 选择数字1 下一步选择Y 不管后面报不报错 3. ...
- php 使用GD库压缩图片,添加文字图片水印
先上一个工具类,提供了压缩,添加文字.图片水印等方法: image.class.php <?php class Image { private $info; private $image; pu ...
- Linux上Makefile管理java项目
前面文章讲到了Linux上通过.spec文件与rpmbuild命令将java程序打包为RPM安装包, 现阶段遇到新的需求: 使用Makefile来操纵java的编译.打包 该需求以前面的内容为基础 可 ...