STL库的内存配置器(allocator)

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

STL源码剖析简体中文完整版(高清晰扫描带目录)PDF 下载地址 

具有次配置力的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> //负责内存空间的配置和释放 2 #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进行构造

STL库的内存配置器(allocator)

下面讲一下我对空间的配置与释放的理解

C++对内存配置的基本操作依靠::operator new()和::operator delete()这两个全局函数,这两个函数只起到分配和释放内存的作用,并不会调用构造函数和析构函数,他们就相当于C语言中的malloc()和free()函数,SGI正是以malloc()和free()进行空间的管理

为了解决内存碎片的问题(当不断地malloc空间时候,找到足够大小的空间就拿来用,不可避免的的会产生内存碎片),于是就有了内存池的概念(内存池就是系统实现给开辟出一大块空间等待使用,当需要空间的时候直接从内存池中取,当内存池中的内存也不够使用时,再去Heap中开辟新的空间注入到内存池当中)

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

STL库的内存配置器(allocator)

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

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

STL库的内存配置器(allocator)

STL库的内存配置器(allocator)

注意,这里的freelists是链表!

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

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

下面给出链表节点的实现

1 union obj 2 { 3 union obj *free_list_link; 4 char client_data[1];//The client sees this; 5 };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/3c68495d2d99b4526daad5d9871ec24e.html