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 ...
随机推荐
- VMvare虚拟机的安装及新建虚拟机.
一.VMvare虚拟机的安装 1.首先双击--你下载的安装包,这里我分享百度云盘,供大家下载:http://pan.baidu.com/s/1jImQSZG 2.VMware Workstation ...
- h5可预览 图片ajax上传 (补更),后台数据获取方法---php
原理是 先获取,然后手动转移文件路径,不然会被服务器自动删除 demo如下: <?php header('content-Type:text/html;charset=utf-8'); $fil ...
- npm的理解
一 概念方面 npm的全称是node package manger ,是一个nodejs包管理工具,已经成为非官方的发布node模块包的标准.有了npm可以很快速的找到特定服务器要使用的包,进行下载, ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'portal.hibernate_sequence' doesn't exist, 谈谈主键自增的方式
最近几天几天做项目用到了Spring Data JPA,确实是个好东西,省了很多力气.但是由于刚开始用,也遇到不少头疼的问题,如下,调用JpaRepository接口的save方法保存一个对象到数据库 ...
- PHP面向对象概述
结构化编程 在程序设计的早期,程序用流程图和自顶向下的方法设计.采用这种设计方法,程序员会将一个大的问题分解成更小的任务,然后为每个更小的任务编写一个过程(或函数).最后,程序员会编写一个主过程来启动 ...
- CJOJ 2307 【一本通】完全背包(动态规划)
CJOJ 2307 [一本通]完全背包(动态规划) Description 设有n种物品,每种物品有一个重量及一个价值.但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干 ...
- python基础(7):元祖类型(赋值补充)
前面学了列表和字典,今天我们看一个和列表相似的类型元祖. 预习: 简单购物车 实现打印商品详细信息,用户输入商品名和购买个数,则将商品名,价格,购买个数加入购物列表,如果输入为空或其他非法输入则要求用 ...
- java.util.Arrays类
前言:java.util.Arrays类的技术文档请查看Oracle官网 1.Arrays类常见方法: 本文参考资料:百度文库:Oracle官网:第三方中文技术文档
- spring加载异常
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' ...
- (转)XML中必须进行转义的字符
场景:在工作中接触到很多xml文件,为了更好的操作这些文件,所有很有必要熟知xml文件的相关语义. 1 引入 编写XML代码经常遗漏的常识: XML实体中不允许出现"&", ...