正在学习中,如果有错,还请多多指教,根据不断的理解,会进行更改,更改之前的样子都会保留下来,记录错误是最大的进步,嗯嗯!

具有次配置力的SGI空间配置器(SGI是STL的一种版本,也有其他的版本)

这里我就不贴出来具体成员和接口的实现了,网上可以搜到STL的源码

C++中,new一个变量可以分为两个阶段,1.分配空间 2.调用构造函数;delete变量也分为两个步骤,1.调用析构函数 2.释放空间

SGI的alloc将这两部分分开,让空间的分配释放和构造析构由不同的函数调用,区分他们的操作

空间的分配和释放由alloc::alloclate()  alloc::dealloclate()实现 构造和析构由alloc::construct() alloc::destory()函数负责,他们在头文件

#include<stl_alloc.h> //负责内存空间的配置和释放 #include<stl_construct.h> //负责对象内容的构造和析构 这两个头文件都包含在#include<memory>当中

先讲一下析构和构造的大概思路  

    • 这里提到一个概念_type_traits<T>(这是个模板),首先通过value_type()获得迭代器所指向对象的类型然后使用_type_traits进行类型判别,该对象是否是trivial(无关痛痒的) destructor,我对这里的理解是,当迭代器所指对象的类型为POD(Plain Old Data)类型(PS:POD类型可以理解为传统的C语言类型,就是int那一类的)是不需要专门调用析构函数的,等待系统自动释放int所占用的空间即可,但当迭代器所指对象的类型为string对象(或者是其他你自己写的类的对象),就不能依靠系统,需要调用专门的析构函数挨个析构。进行类型判别之后,就可以提高工作效率。(destory()对char*等类型也有相应的特化)
    • 构造函数就采用泛式构造,使用new进行构造
  • 下面讲一下我对空间的配置与释放的理解
    • C++对内存配置的基本操作依靠::operator new()和::operator delete()这两个全局函数,这两个函数只起到分配和释放内存的作用,并不会调用构造函数和析构函数,他们就相当于C语言中的malloc()和free()函数,SGI正是以malloc()和free()进行空间的管理
    • 为了解决内存碎片的问题(当不断地malloc空间时候,找到足够大小的空间就拿来用,不可避免的的会产生内存碎片),于是就有了内存池的概念(内存池就是系统实现给开辟出一大块空间等待使用,当需要空间的时候直接从内存池中取,当内存池中的内存也不够使用时,再去Heap中开辟新的空间注入到内存池当中)

下面就比较重要了,SGI空间配置器采用了两级配置器,分为第一级配置器和第二级配置器,第一级配置器就是拿malloc()实现的,第二级配置器采用了内存池的概念;

先来讲第一级配置器,第一级配置器的实现就是用的malloc()(因为很重要所以多说几遍),它会不断地尝试开辟内存,如果没有内存可供开辟,就会尝试释放空间,然后再取尝试开辟空间,第一级配置器比较重要的一点就是实现了类似C++中new-handler机制,用来处理内存不足的情况

内存池是使用链表结构实现的(个人感觉和哈希桶的方法类似),而不采用顺序表,这样就可以更好的解决内存碎片的问题了。

注意,这里的freelists是链表!

注意!这里之前写的不太清楚,freelists是一个顺序表,每一个单元下边都连接这一个链表,当区块被客端(client)使用就会像上图一样将区块拨出去,然后改变指针指向下一个节点(就是采用头删)

每个链表节点所管理的区块大小也是不一样的,第一个节点管理8bytes,第二个16bytes。。。以此类推,最后一个节点管理128bytes,所以当超过128字节第二级配置器无法处理,就只好调用第一级配置器(内存不足时也会调用第一级配置器,因为第一级配置器里面有内存不足处理例程)

下面给出链表节点的实现

 union obj
{
union obj *free_list_link;
char client_data[];//The client sees this;
};

里面的联合体指针就是指向下一个节点的指针,那个char是指向实际内存块的指针,采用联合体可以减少内存的消耗,不必专门维护一个指向下一个节点的指针

当节点所指的内存块是空闲块时,obj被看做一个指针,指向下一个节点,当节点已经被分配了内存之后,被视为一个指针,指向实际区块

当分配函数allocate()(alloc中申请内存的函数)发现没有可用的区块之后,就会去内存池中申请新的区块(调用chunk_alloc()函数) ,默认申请20个区块,当内存池的可用内存不足20个区块,有多少给多少,如果连一个区块的内存都不够,就往内存池中注入内存(就是再去开辟一些放进内存池里),就会去free_lists中遍历,寻找内存池分配给自由链表但是却处于空闲状态的节点,将这些节点的存储空间归还个内存池,再递归去使用chunk_alloc()函数判断是否空间够分配;如果很不幸,还是不够用,那么注意!!会将内存池中剩余的小空间分配成低位区块分给自由链表(就是说假如需要申请16个字节的节点区块,不够了,但是内存池中有8个字节的空间,当然不能够浪费咯,赶紧分配出去)然后去往内存池中注入内存(就是再去开辟一些放进内存池里)。

这个是《STL源码剖析》里的一个例子

当整个系统堆得内存都不够了的时候,就chunk_malloc()就会四处寻找可用内存,尝试释放一些没用的空间,如果还是无法找到就去调用第一级配置器,因为一级配置器里有内存不足处理例程

STL库的内存配置器(allocator)的更多相关文章

  1. 自己动手实现STL 01:内存配置器的实现(stl_alloc.h)

    一.前言 在STL中,容器是其中的重中之重,基本的STL中的算法,仿函数等都是围绕着容器实现的功能.而,内存配置器,是容器的实现的基础.所以,我第一次要去编写便是内存配置器的实现.在STL中,内存配置 ...

  2. C++ STL学习之 空间配置器(allocator)

    众所周知,一般情况下,一个程序包括数据结构和相应的算法,而数据结构作为存储数据的组织形式,与内存空间有着密切的联系. 在C++ STL中,空间配置器便是用来实现内存空间(一般是内存,也可以是硬盘等空间 ...

  3. 《STL源码剖析》chapter2空间配置器allocator

    为什么不说allocator是内存配置器而说是空间配置器,因为空间不一定是内存,也可以是磁盘或其他辅助介质.是的,你可以写一个allocator,直接向硬盘取空间.sgi stl提供的配置器,配置的对 ...

  4. SGI STL内存配置器存在内存泄漏吗?

    阅读了SGI的源码后对STL很是膜拜,很高质量的源码,从中学到了很多.温故而知新!下文中所有STL如无特殊说明均指SGI版本实现. STL 内存配置器 STL对内存管理最核心部分我觉得是其将C++对象 ...

  5. STL内存配置器

    一.STL内存配置器的总体设计结构 1.两级内存配置器:SGI-STL中设计了两级的内存配置器,主要用于不同大小的内存分配需求,当需要分配的内存大小大于128bytes时, 使用第一级配置器,否则使用 ...

  6. STL之空间配置器allocator

    摘要 C++STL的空间配置器将内存的分配.释放,对象的构造.析构都分开执行,内存分配由alloc::allocate()负责,内存的释放由alloc::deallocate()负责:对象的构造由:: ...

  7. STL——模拟实现空间配置器

    目录 问题 SGI版本空间配置器-std::alloc 一级空间配置器 二级空间配置器 Refill.chunkAlloc函数 最后,配置器封装的simple_alloc接口 问题 我们在日常编写C+ ...

  8. STL-空间配置器(allocator)

    STL的空间配置器作为STL六大部件的重要组成部分,它总是隐藏在一切组件的背后.它主要负责动态空间的分配.释放等管理工作.整个STL的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以置 ...

  9. C++ 空间配置器(allocator)

    C++ 空间配置器(allocator) 在STL中,Memory Allocator 处于最底层的位置,为一切的 Container 提供存储服务,是一切其他组件的基石.对于一般使用 STL 的用户 ...

随机推荐

  1. Managing IIS Log File Storage

    Managing IIS Log File Storage   You can manage the amount of server disk space that Internet Informa ...

  2. MySQL_订单类型细分_20161222

    #目前在做一个各城市日订单角度的对比分析,因此需要对订单类型进行一下规整.由于App上产品活动许多,查询了多个表,将订单类型规则进行了统一,优惠券和满减券不能同时使用,创建的这两个表都是以订单ID为k ...

  3. bat批处理重命名问题

    因为要重命名的字符串中有文字,导致重命名出来的文件名都变为乱码了,查理一下需要加两句话 1. @Echo Off Chcp 65001>nul SetLocal EnableDelayedExp ...

  4. 使用Docker Image跑Gitlab

    下载gitlab docker镜像 docker pull gitlab/gitlab-ce:latest 启动gitlab服务 sudo docker run --detach \ --hostna ...

  5. kindeditor多图片上传找不到action原来是private File upload成员变量惹得祸

    kindeditor多图片上传找不到action原来是private File upload成员变量惹得祸

  6. CSS考试题目

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. java环境基础步骤 svn

    eclipse里安装SVN插件,一般来说,有两种方式: 直接下载SVN插件,将其解压到eclipse的对应目录里 使用eclipse 里Help菜单的"Install New Softwar ...

  8. taiyi_interview(Introduction To Database Refactoring)

    Introduction To Database Refactoring 原文链接:by Scott W. Ambler:http://www.tdan.com/view-articles/5010/ ...

  9. Python—判断变量的基本类型

    type() >>> type(123)==type(456) True >>> type(123)==int True >>> type('ab ...

  10. C语言获取时间

    转载:http://www.cnblogs.com/fzhe/archive/2012/11/06/2757858.html C语言获取系统时间的几种方式   C语言中如何获取时间?精度如何? 1 使 ...