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.合并

  

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

  

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

  

  

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

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

 
 

malloc内存分配与free内存释放的原理的更多相关文章

  1. SQL SERVER 内存分配及常见内存问题(2)——DMV查询

    原文:SQL SERVER 内存分配及常见内存问题(2)--DMV查询 内存动态管理视图(DMV): 从sys.dm_os_memory_clerks开始. SELECT [type] , SUM(v ...

  2. SQL SERVER 内存分配及常见内存问题(1)——简介

    原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解 ...

  3. (转)java内存分配分析/栈内存、堆内存

    转自(http://blog.csdn.net/qh_java/article/details/9084091) java内存分配分析/栈内存.堆内存 java内存分配分析 本文将由浅入深详细介绍Ja ...

  4. rt-thread中动态内存分配之小内存管理模块方法的一点理解

    @2019-01-18 [小记] rt-thread中动态内存分配之小内存管理模块方法的一点理解 > 内存初始化后的布局示意 lfree指向内存空闲区首地址 /** * @ingroup Sys ...

  5. 目录_Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)

    1.Java直接内存与堆内存-MarchOn 2.Java内存映射文件-MarchOn 3.Java Unsafe的使用-MarchOn 简单总结: 1.内存映射文件 读文件时候一般要两次复制:从磁盘 ...

  6. C程序的内存分配及动态内存

    1.程序内存的分配 一个由C/C++编译的程序占用的内存分为以下几个部分:1)栈区(stack) — 由编译器自动分配释放 , 存放为运行函数而分配的局部变量. 函数参数. 返回数据. 返回地址等. ...

  7. Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:什么是静态内存什么又是动态内存呢? 静态内存:是指在程序开始运行时由编译 ...

  8. SQL SERVER 内存分配及常见内存问题 简介

    一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQ ...

  9. C++_类和动态内存分配1—动态内存和类

    静态类成员 num_strings成员声明为静态存储类.静态类成员有一个特点:无论创建了多少对象,程序都只创建一个静态类变量副本.也就是说,类的所有对象共享一个静态成员.num_strings成员可以 ...

随机推荐

  1. Chromium Graphics: GPUclient的原理和实现分析之间的同步机制-Part I

    摘要:Chromium于GPU多个流程架构的同意GPUclient这将是这次访问的同时GPU维修,和GPUclient这之间可能存在数据依赖性.因此必须提供一个同步机制,以确保GPU订购业务.本文讨论 ...

  2. 2.cocos2dx 3.2在语法的差异,lambada使用表达式和function和bind使用功能

    1        打开 - 内置T32  Cocos2dx-3.2一个专案 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG90b3R1enVvcXVhb ...

  3. 采用RedisLive监控Redis服务

    1.基础环境安装https://pypi.python.org/packages/source/b/backports.ssl_match_hostname/backports.ssl_match_h ...

  4. Tomcat剖析(二):一个简单的Servlet服务器

    Tomcat剖析(二):一个简单的Servlet服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三) ...

  5. HDU2586

    最近的共同祖先反复问的问题. #include <iostream> #include <algorithm> #include <vector> #include ...

  6. Myeclipse重装后的必要配置

    一.JDK位置 每台机器同意多个jdk版本号存在,编译时选择须要使用的jdk就可以.MyEclipse->Properties->Java->Installed JRES选择jdk位 ...

  7. 关于fork()函数的作用

    (1)    先看一个实例: #include <unistd.h>; #include <sys/types.h>; main () {           pid_t pi ...

  8. Ormlite or()的使用

    如题,由于不熟悉这个框架的API,所以用的时候出错了,直接上代码 public List<Type> getAllBetweenDate(String start, String end) ...

  9. java通过SVG导出图片

    import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import ja ...

  10. (C语言)共用体union的使用方法举例

    曾经在学校学习C语言的时候一直搞不懂那个共用体union有什么用的.工作之后才发现它的一些妙用,现举比例如以下: 1. 为了方便看懂代码. 比方说想写一个3 * 3的矩阵,能够这样写: [ 注:以下用 ...