【STL】 SGI空间配置器(一):介绍

一、代码结构

先看一段伪代码

class Foo{...};
Foo* pf = new Foo; //配置内存,然后析构对象
delete pf; //将对象析构

new算式内含两阶操作:

  • 调用::operator new 配置内存。
  • 调用Foo::Foo()构造对象内容。

delete算式也内含两阶操作:

  • 调用Foo::~Foo()将对象析构。
  • 调用::operator delete 释放内存。

为精密分工,STL allocator决定将这两阶段操作区分开来。
【内存操作】

  • 由 alloc::allocate()负责配置。
  • 由 alloc::deallocate()负责释放。

【对象操作】

  • 由 ::construct()负责构造。
  • 由 ::destroy()负责析构。

STL标准将配置器定义于之中。文件结构如下:
【STL】 SGI空间配置器(一):介绍_第1张图片
上述初步说了下内存配置与对象构造和对象析构在STL结构中的关系。接下来着重讲解内存配置相关。

二、空间配置器(std::alloc)

2.1 背景

在软件开发过程中因程序需求,不可避免的使用很多的小块内存(基本类型以及小内存的自定义类型),于是乎就会在程序中动态的申请和释放,这样就会产生如下问题:

  • 内存碎片。(这里指外碎片)
  • 一直因小块内存而进行内存申请、释放,这样会产生性能问题。

注意:
【内碎片】
指因为内存对齐/访问效率(CPU取址次数)而产生,如用户需要3字节,实际得到4或者8字节,
其中的多余大小空间就是浪费掉的。

【外碎片】
系统内存总量足够,但是不连续,所以无法分配给用户使用而产生的浪费。

2.2 设计

SGI STL对空间配置器的设计哲学如下:

  • 向system heap要求空间。
  • 考虑多线程(multi-threads)状态。
  • 考虑内存不足时的应变措施。
  • 考虑过多“小型区块”可能造成的内存碎片问题。

这里讨论的过程未包括多线程处理状态。
C++的内存配置基本操作是 ::operator new(),内存释放基本操作是::operator delete()。这两个全局函数相当于C的malloc()free()函数。SGI正是以malloc()free()完成内存的配置和释放。
为解决小型区块可能造成的内存碎片问题,SGI设计了双层配置器:

  1. 第一级配置器直接使用malloc()free()
  2. 第二级配置器则视情况采用不同的策略,当配置区块超过128bytes时,则调用第一级配置器,当配置区块小于128bytes时,为降低额外负担则采用复杂的memory pool整理方式,而不再求助于第一级配置器。

至于是否只开放第一级配置器,还是同时开放第二级配置器,取决于__USE_MALLOC是否被定义。
SGI STL并未定义,所以SGI是第一级和第二级都开放的。

# ifdef __USE_MALLOC
...
typedef __malloc_alloc_template<0> malloc_alloc;
typedef malloc_alloc alloc; // 令 alloc 為第一級配置器
# else
...
// 令 alloc 為第二級配置器
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
#endif /* ! __USE_MALLOC */
2.3 配置器关系

【STL】 SGI空间配置器(一):介绍_第2张图片

2.4 配置器接口包装和运用方式

【STL】 SGI空间配置器(一):介绍_第3张图片


参考链接:
https://www.cnblogs.com/lang5230/p/5556611.html

你可能感兴趣的:(STL,空间配置器,STL,《STL源码剖析》阅读总结)