SGI STL 内存分配方式及malloc底层实现分析
在STL中考虑到小型区块所可能造成的内存碎片问题,SGI STL设计了双层级配置器,第一级配置器直接使用malloc()和free();第二级配置器则视情况采用不同的策略:当配置区块超过128bytes 时,则视之为足够大,便调用第一级配置器;当配置区块小于128bytes时,则视之为过小,为了降低额外负担,便采用复杂的内存池的方式来整理,而不再求助于第一级配置器。
<stl_alloc.h>内定义了两个template,一个是 __malloc_alloc_template,这是sgi stl的一级配置器,它的allocate()直接使用malloc()而deallocate()直接使用free(),同时,它模拟C++的 set_new_handler()处理内存不足的状况。
第二个是__default_alloc_template,它维护了16个free list,每个list上集合着大小分别为8,16,24,...128大小的内存块。内存池以malloc()配置而得,如果内存不足,转调用第一级配 置器,因为那里设置了内存不足的处理程序。如果请求的内存块大小大于128bytes,就转调用第一级配置器。另外定义了两个alloc,一个是 debug_alloc,每次配置一块内存时,都会配置比需求多8byte的空间以存储空间大小,通过assert语句来检查会不会内存溢出。另一个是 simple_alloc,定义了两个版本的allocate和deallocate,它们都只是单纯的转调用。sgi stl容器全都使用simple_alloc接口。free-list的节点巧妙地使用了一个union结构来管理链表:

union obj{
union obj* free_list_link; //当作为自由链表的一个结点时,存储其下一个节点的地址
char client_date[]; //当其作为返回值时,返回的正好是分配内存的首地址
}
每次配置器需要向系统要内存的时候,都不是按客户需求向系统申请的,而是一次性向系统要了比需求更多的内存,放在内存池里,有一个free_start和 free_end指示剩余的空间(也就是说内存池剩余的空间都是连续的,因此每次重新向system heap要空间的时候,都会把原先内存池里没用完的空间分配给合适的free list。)当free-list中没有可用区块了的时候,会首先从内存池里要内存,同样,也不是以按客户需求要多少块的,而是一次可能会要上20块,如 果内存池内空间允许的话,可能会得到20个特定大小的内存,如果内存池给不了那么多,那么就只好尽力给出;如果连一个都给不出,那么就要开始向系统即 system heap要空间了。换算的标准是bytes_to_get=2*total_bytes+ROUND_UP(heap_size>>4)。这 个时候使用的是malloc,如果没成功,就尝试着从大块一点的freelist那里要一个来还给内存池,如果还是不行,那么会调用第一级空间配置器的 malloc::allocate,看看out-of-memory机制能做点什么不。
![]()
总结起来整个过程大概是这样的,假设我们向系统要x大小的内存,
(1)x大于128byte,用第一级配置器直接向系统malloc,至于不成功的处理,过程仿照new,通过set_new_handler来处理,直到成功返回相应大小的内存或者是抛出异常或者是干脆结束运行;
(2)x小于128byte,用第二级配置器向内存池相应的free_list要内存,如果该freelist上面没有空闲块了,
(2.1)从内存池里面要内存,缺省是获得20个节点,如果内存池中剩余的空间不能完全满足需求量,但足够供应一个(含)以上的区块,则应尽力满足需求。
(2.2)
如果一个都不能够满足的话,则从系统的heap里面要内存给到内存池,换算的标准是
bytes_to_get=2*total_bytes+ROUND_UP(heap_size>>4),申请的大小为需求量的两倍加上一个
附加值,如果内存池中还有剩余的内存,则将残余零头分配给适当的free list,这时使用的是系统的malloc,如果要不到:
(2.3)从比较大的freelist那里要内存到内存池,如果还是要不到:
(2.4)
从系统的heap里面要内存给到内存池,换算标准跟2.2一样,但是这时候使用的是第一级配置器的allocate,主要是看看能不能通过
out_of_memory机制得到一点内存。所以,freelist总是从内存池里要内存的,而内存池可能从freelist也可能从系统heap那里
要内存。
SGI
STL的alloc的主要开销就在于管理这些小内存,管理这些小内存的主要开销就在于,每次freelist上的内存块用完了,需要重新要空间,然后建立
起这个list来。freelist上的内存,会一直保留着直到程序退出才还给系统。但这不会产生内存泄漏,一来是管理的都是小内存,二来是,占用的内存
只会是整个程序运行过程中小内存占用量最大的那一刻所占用的内存。

SGI STL 内存分配方式及malloc底层实现分析的更多相关文章
- C语言跟内存分配方式-alloc malloc calloc
转载:http://blog.csdn.net/ubuntulover/article/details/7581317 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整 ...
- STL内存分配方式
关于STL用的很多比如map, vector, set, queue, stack等等.很少关注它的内存分配情况,但是经常遇到比如使用map,不停的在map中插入了一些很小的对象,然后释放了一些,然后 ...
- 内存分配方式,堆区,栈区,new/delete/malloc/free
1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数时 ...
- C/C++ 内存分配方式,堆区,栈区,new/delete/malloc/free
内存分配方式 内存分配方式有三种: [1] 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量, static 变量. [2] 在栈上创建.在执行函 ...
- c/c++内存分配方式(转)
原文链接:http://blog.csdn.net/jing0611/article/details/4030237 1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在 程序编译 ...
- [转载]C语言程序的内存分配方式
"声明一个数组时,编译器将根据声明所指定的元素数量为数量为数组保留内存空间."其实就是编译器在编译的过程中,会加入几条汇编指令在程序里处理内存分配,并不是说编译时就分配了内存,不要 ...
- 转 C/C++内存分配方式与存储区
C/C++内存分配方式与存储区 C/C++内存分配有三种方式:[1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量.[2]在栈 ...
- C和C++内存分配方式记录
C. C++中内存分配方式可以分为三种: (1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...
- C++内存分配方式——(别人的博客)
http://www.cnblogs.com/easonpan/archive/2012/04/26/2471153.html http://blog.csdn.net/chen825919148/a ...
随机推荐
- VB6获取Chrome地址栏的URL信息
上篇写到了获取IE8浏览器URL的一般方法,那这篇就写下chrome的URL怎么获取.事实上,早期的chrome版本可以通过跟IE8差不多方式获取到URL信息.但是,现在chrome的控件都是Dire ...
- vijos1051题解
题目: 圣诞老人回到了北极圣诞区,已经快到12点了.也就是说极光表演要开始了.这里的极光不是极地特有的自然极光景象.而是圣诞老人主持的人造极光. 轰隆隆--烟花响起(来自中国的浏阳花炮之乡).接下来就 ...
- 分享一次Oracle数据导入导出经历
最近工作上有一个任务要修改一个比较老的项目,分公司这边没有这个项目数据库相关的备份,所以需要从正式环境上面导出数据库备份出来在本地进行部署安装,之前在其它项目的时候也弄过这个数据库的部署和安装,也写了 ...
- vsftpd3.0之匿名用户配置
有时候工作中为了方便上传下载文件,又不想在系统中添加用户并为用户创建密码,这时候就可以用匿名用户方式搭建FTP服务器,当然安全性我们不说,今天就为实现这么个简单而粗爆的FTP服务器,来看看都需要哪些配 ...
- Mac之OS系统下搭建JavaEE环境 <三> 之Eclipse 与 IntelliJ IDEA 的安装配置
三.Eclipse 与 IntelliJ IDEA 的安装配置 1.Eclipse的安装配置 1 下载eclipse 到官网 https://www.eclipse.org/downloads/ecl ...
- java Static的使用
static是一个静态修饰符,用于修饰成员(成员变量,成员函数).<thinking in java>对staic的使用场景有下面2种定义:“一种情形是只想用一个存储区域来保存一个特定的数 ...
- select可选择、同时可自行输入
HTML部分: <li class="bl-form-group"> <label>诊断医生</label> <div class=&qu ...
- (转)Java并发编程:深入剖析ThreadLocal
Java并发编程:深入剖析ThreadLoca Java并发编程:深入剖析ThreadLocal 说下自己的理解:使用ThreadLocal能够实现空间换时间,重在理解ThreadLocal是如何复制 ...
- Linux学习-->linux系统在移动硬盘的安装
由于自己看了一些文章和linux的好奇,想来一窥Linux的奥秘,因此自己准备学习使用Linux系统,这里记录下自己的安装过程,方便以后自己重装系统时进行查阅. 参考的书籍是鸟哥的<Linux私 ...
- Python 获取当前路径的方法
Python2.7 中获取路径的各种方法 sys.path 模块搜索路径的字符串列表.由环境变量PYTHONPATH初始化得到. sys.path[0]是调用Python解释器的当前脚本所在的目录. ...