Dynamic Memory Allocate(动态内存分配)
来源:互联网 发布:linux基础面试题 编辑:程序博客网 时间:2024/06/05 17:03
- 介绍
- 空闲链表
- implicit list
- explicit list
- segregated list
- Garbage Collection
刚刚写完malloc的小伙伴估计现在还心有余悸~ 不过写完以后在看书,你会发现书上的东西很简单。
转载请注明出处:http://blog.csdn.net/c602273091/article/details/53576494
介绍
动态内存分配:在程序运行时给相应变量分配内存。因为在很多时候我们只有在运行的时候才知道内存,提前分配要么就会太大,浪费了空间;要么就是太小,信息存放不下。动态内存是存在于堆空间上的。
动态内存分配器分为显式和隐式,并且在管理的时候把内存分成固定的块。显示的如malloc,new,需要自己申请和释放。隐式的如java中的垃圾回收。
在内存中,动态内存分配区域如下:
在进行malloc内存分配的时候,内部(分配给一个比payload更大的区域存放所需数据,一般是为了满足对齐要求,保留该块的一个数据结构)和外部碎片(本来可以满足请求,但是因为不连续)会降低utilization。
对于空闲链表的维护,可以使用implicit list, explicit list, segregated list, balance tree(red black tree)进行记录。下面就介绍这些链表。
空闲链表
implicit list
隐式链表就是说它没有显式地使用指针,但是可以向链表一样找到下一个节点。这个结构就是有一个头部,头部说明这个块的大小以及是否已经分配。接着是payload,然后是对齐的pending。当然这里没有画出footer,用于合并。
下面就是一个例子:
寻找空闲块的位置:块的释放和分配的过程中,设计选取块的位置。一般来说就是最先适配、最近适配、最优适配。最优适配节约空间,但是速度比较慢,在做malloc的时候不适用。使用最近适配,一般会比最先适配快,但是utilization降低了。
块的分割:在我们分配一个块的时候,如果剩余块比最小块更大,那么就可以把剩余块加入到空闲链表里面。
块的合并:当一个块被释放的时候,它会查找前后两个块是否空闲,然后合并。找到后面的块很容易,但是前面的块却找不到。所以这里加入了footer,进行合并。当然,这里说的合并是快速合并,不是推迟合并。推迟合并的话,就是扫描整个链表,看是否需要合并。推迟合并就不需要footer了。这里的footer就是大家熟悉的边界标记。
explicit list
在隐式链表上提取出来的,因为隐式链表太慢,而且需要了解到的是只有空闲链表才需要记录,已经分配的,不需要记录。那么显示链表就被提出了。
所以给空闲块增加了前驱和后驱,形成双向链表指向前后的空闲块。有了双向链表,增加,删除,修改一个节点就变得非常轻松。
在插入新节点的时候,可以用LIFO和FIFO。它们的优缺点如下图:我发现用FIFO写malloc比LIFO速度会更慢一些,但是utilization会更大。因为LIFO一般都是以最大的heap的头那块区域接近。
它和隐式链表对比,当然是速度更快,但是内部碎片很可能更大。
segregated list
分离空闲链表就是把空闲块根据大小的不同,分配到了不同的地方。
分离的空闲链表的整个数据结构可以和显示链表一样,就是多声明几个指针用于存储不同大小的空闲块。
平衡树在书上没有讲了,平衡树也就是把空闲块插入到平衡树里面,从找适配块的速度,空间利用率方面都可以大大提高。
Garbage Collection
内存管理者可以知道一个存的东西是不是指针。
一些经典的垃圾回收算法:
把内存看成是有向图,那么每个块就是一个节点,每个指针就是边。如果没有在这个有向图的范围内的内存,都可以看成垃圾。
当不在范围内的块就被标记,然后就被清理。
与内存有关的错误:
看懂下面这幅图,说明你懂指针了。
下面是我们对指针使用比较容易犯的错误。
解决办法:
当然,了解动态内存最好的办法就是实现它。开始做你的malloc吧~
PS: the ppt slide is cut from CMU 18-600 Click Here
- Dynamic Memory Allocate(动态内存分配)
- 动态内存分配 (Dynamic memory)
- 动态内存分配 (Dynamic memory)
- XZ_iOS之动态内存分配(Dynamic memory allocation)
- Mount共享无法分配内存(Cannot allocate memory)
- Dynamic Memory Allocation in Critical Embedded Systems/关于嵌入式系统中的动态内存分配
- Primer plus C++ 第十一章 类和动态内存分配_反面理解String类(class and dynamic memory allocation)
- calloc, malloc, free, realloc - Allocate and free dynamic memory
- ALLOCATE语句分配FORTRAN动态数组方法
- Cpp的动态存储Dynamic Memory-笔记
- Spark动态资源分配-Dynamic Resource Allocation
- Spark动态资源分配-Dynamic Resource Allocation
- 动态资源分配(Dynamic Resource Allocation)
- Allocate aligned memory
- Memory allocate in Ogre
- MPI_Probe-Dynamically allocate memory
- Android cannot allocate memory
- 动态内存分配
- 什么是回调函数?回调函数适合在什么情况下使用?
- Java学习者论坛【申明:来源于网络】
- GimbalLock万向节锁与四元数旋转
- Redis源码解析——有序整数集
- 日志收集之flume-ng源码分析
- Dynamic Memory Allocate(动态内存分配)
- Matrix Problem : Array Practice
- Bot Framework 核心概念:添加频道数据
- struts的MVC和spring的MVC的区别
- java8接口的新增功能
- 2016年12月11日学习总结----阶段总结
- 一般人我不告诉的bug
- Eclipse安装jbpm6插件并测试Hello示例
- 积极的环境能够改变人(幸福课笔记4)