STL中的内存分配方式

news/2024/11/8 6:48:47/

转自(http://www.cnblogs.com/LUO77/p/5824625.html)

在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结构来管理链表:

这里写图片描述

每次配置器需要向系统要内存的时候,都不是按客户需求向系统申请的,而是一次性向系统要了比需求更多的内存,放在内存池里,有一个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上的内存,会一直保留着直到程序退出才还给系统。但这不会产生内存泄漏,一来是管理的都是小内存,二来是,占用的内存 只会是整个程序运行过程中小内存占用量最大的那一刻所占用的内存。

这里写图片描述


http://www.ppmy.cn/news/241124.html

相关文章

S32K144内存分配

本文将通过实际的工程代码介绍NXP S32K144单片机变量地址分配&#xff0c;应用笔记仅用于自己学习及大家参考。 示例代码如下&#xff1a; uint8_t num_byte[4]; uint32_t num_word; const uint32_t num_word_const 0x1234; uint32_t *point_heap; int main(void) { uint8_t…

内存管理(一)——内存分配

前言 我们都知道&#xff0c;计算机工作的过程概括起来就是 CPU 去内存中读取指令并执行的过程&#xff0c;但是如果运行我们的程序直接操作物理内存&#xff0c;将会引发很多的问题&#xff08;比如不同进程之间访问/修改的隔离、权限等等&#xff09;&#xff0c;所以爱操心…

DDR3地址及容量大小

DDR3 地址线 DDR3为减少地址线&#xff0c;把地址线分为行地址线和列地址线&#xff0c;在硬件上是同一组地址线&#xff1b;地址线和列地址线是分时复用的&#xff0c;即地址要分两次送出&#xff0c;先送出行地址&#xff0c;再送出列地址。 一般来说列地址线是10位&a…

STM32——根据地址计算存储空间的大小

首先要知道 1MB1024KB 1KB1024Byte 1Byte8bit 存储空间大小结束地址-起始地址1&#xff08;用十进制来算&#xff0c;得到结果的单位是Byte&#xff09; 十六进制与2进制转换表 十六进制2进制00000100012001030011401005010160110701118100091001A&#xff08;10&#xf…

STL六大组件之——分配器(内存分配,好深奥的东西)

SGI设计了双层级配置器&#xff0c;第一级配置器直接使用malloc()和free()&#xff0c;第二级配置器则视情况采用不同的策略&#xff1a;当配置区块超过128bytes时&#xff0c;视之为“足够大”&#xff0c;便调用第一级配置器&#xff1b;当配置区小于128bytes时&#xff0c;视…

kmalloc分配大小的限制

原文地址&#xff1a;http://linux.chinaunix.net/techdoc/net/2009/04/28/1109237.shtml #################################################################################################################################### kmalloc是通过cache来实现的, 只不过每次…

采用链接分配方式进行外存分配时,可采用的两种形式及其特点。假定磁盘块大小为4K,对于128G的硬盘,其文件分配表FAT需占用多少存储空间?

采用链接分配方式进行外存分配时&#xff0c;可采用的两种形式及其特点。假定磁盘块大小为4K&#xff0c;对于128G的硬盘&#xff0c;其文件分配表FAT需占用多少存储空间&#xff1f; 隐式链接&#xff1a;除文件的最后一个盘快外&#xff0c;每个盘快中都存有指向下一个盘快的…

内存分配方式

一、内存分配方式 内存分配有三种方式&#xff1a; 1、从静态存储区分配。这种方式是在程序编译的时候已经分配好&#xff0c;并且这块内存在程序的整个运行期间都存在。如全局变量&#xff0c;static变量。 2、在栈上创建。在执行函数的时候&#xff0c;函数内局部变量的存储单…