SGI-STL简记(一)-内存分配器解析

defalloc.h :
    默认分配器allocator:
        早期专用于HP的默认分配器,目前是不被赞成使用的;
        仅提供了allocator模板简单封装,重声明(或类型外抛)一些必要的类型Type,此外提供申请和释放内存接口(底层直接使用全局::operator new和::operator delete进行内存分配和释放);
        取引用的地址、取常引用的常量地址等接口;
        allocate:内部取消new申请内存时失败跳转处理函数而是直接抛出异常;
        init_page_size:申请页大小下最大空间大小,采用4K(4096)/sizeof(T)计算;
        max_size:申请最大空间大小,采用UINT_MAX/sizeof(T)计算。
        此外模板特化allocator<void>,仅重声明指针类型;

stl_alloc.h:
    STL内部的分配器allocator(默认的__default_alloc_template模板类采用线程安全的分配器):
        同默认分配器重声明了一些必要的类型Type、申请和释放内存接口、取引用的地址、取常引用的常量地址、max_size:申请最大空间大小,采用size_t(-1)/sizeof(T)计算;
        不同点在于其底层内存处理使用的是一个alloc(实际为__default_alloc_template模板类或malloc_alloc(__malloc_alloc_template)),通过它进行申请和释放内存;
        提供了默认构造、析构、赋值构造、构造construct(通过"放置"new)、销毁destroy(通过调用其析构函数)、提供rebind类结构声明;
        此外模板特化allocator<void>,重声明了一些必要的类型Type;
    STL内部的分配适配器__allocator(通过模板参数提供底层内存分配):
        同上者一样,不过底层内存处理为一个模板参数提供的类型对象__underlying_alloc;当__allocator<_Tp, alloc>时则与allocator<_Tp>相同;
    底层内存处理模板类__default_alloc_template(可认为其为一个内存池的模板类):
        模板参数分别为bool threads, int inst,threads为true则为线程安全,否则只能用于单线程情况;inst只是一个标识,用以支持多个不同的__default_alloc_template实例;
        _ALIGN:字节对齐8字节;
        _MAX_BYTES:最大字节128字节,超过则调用malloc_alloc分配;
        _NFREELISTS:释放后的指针列表_S_free_list大小128/8=16;
        _S_free_list:释放后列表数组,保存着指向各索引空间链表地址的指针;
        _S_start_free(0)、_S_end_free(0)、_S_heap_size(0):块分配状态;
        _S_node_allocator_lock:分配器锁对象;
        内部自动锁类_Lock;用于包装_S_node_allocator_lock加解锁,windows下使用的是原子锁,其他平台下使用的是引用计数加pthread_mutex_lock;
        _Obj:联合类,封装链表指针或链表下一个对象,为了节省空间把申请到的空间作为指向下一个节点内存;
        供外部调用接口allocate分配内存,deallocate释放内存,reallocate重新申请内存;
        _S_round_up:字节对齐,调整到_ALIGN字节的整数倍(n + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1));
        _S_freelist_index:计算当前申请字节大小在_S_free_list列表中的位置索引(n + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1,范围0~15;
        故得出_S_free_list保存的链表申请布局如:[8, 16, 24, 32, 40, 48, 56, 64,..., 128],每个节点链表为单链表,最新的节点申请和释放均为表头,
        这样可加速申请和释放操作,事实上释放的节点直接加载节点链表的表头并不free,若链表为空则申请相应索引下大小的空间内存;
        _S_refill、_S_chunk_alloc:填充节点链表以及申请空间内存(事实上_S_chunk_alloc内部在开始申请空间时并不是申请相应空间大小,而是对应申请索引布局下
        字节的更多倍(为了再次避免内存碎片和频繁申请)(具体操作细节可以看一下源码实现),_S_refill负责填充_S_chunk_alloc申请后未被使用的链表申请布局拆分至相应
        的节点链表上供下一次直接供给申请使用而无需再申请内存,而后返回一片内存供上层使用);
    __default_alloc_template模板类内部用到的malloc_alloc大块内存分配类(即__malloc_alloc_template<0>模板类):
        __malloc_alloc_template提供对外使用接口:
            allocate:内部调用malloc申请内存,若失败,则调用_S_oom_malloc;
            deallocate:内部直接调用free释放内存;
            reallocate:内部调用realloc重申请内存,若失败,则调用_S_oom_realloc;
            此外还提供了__set_malloc_handler设置申请处理函数;
            _S_oom_malloc:内部通过判断申请处理函数是否为空,若为空则抛出bad_alloc异常,否则执行处理函数并继续循环调用malloc直到申请成功;每次申请前均会
            调用该处理函数;
            _S_oom_realloc:同_S_oom_malloc类型,循环调用realloc重申请;

    依赖关系:分配器__allocator、allocator->分配器模板__default_alloc_template(核心组件)->__malloc_alloc_template(大块内存申请处理)(或全局malloc、free)->
              全局malloc、free;

    __allocator、allocator、__default_alloc_template具备申请管理大、小内存机制(最底层是通过调用malloc/free/remalloc实现)以及锁资源保护(当然也可以用宏设置不加锁,
    此时若上层需要自己维护自己的资源,是否给你的某些资源加锁保护,依赖于具体情况),其他直接调用malloc/free/remalloc实现;

    其他的内存分配适配器模板类:
        simple_alloc简易封装分配器、debug_alloc分配内存前带额外8字节的调试信息封装分配器、_Alloc_traits分配器类型萃取模板类;
        其中_Alloc_traits模板参数的分配器可为特化版本类型,如:allocator、__allocator、__malloc_alloc_template、__default_alloc_template、debug_alloc;
        此外_Alloc_traits模板参数的分配器的_S_instanceless为以上类型时值为true,其他用户自定义类型则为false,当为true时通过rebind获取allocator_type,
        其他则通过相应分配器获取allocator_type,此外还提供了simple_alloc简易封装分配器的_Alloc_type类型;
        _Alloc_traits用在容器模板类的各个角落,并且默认情况下容器的分配器为allocator<T>或alloc(__default_alloc_template或malloc_alloc(__malloc_alloc_template));
        single_client_alloc为__default_alloc_template不加锁时的分配器很快但不安全,malloc_alloc安全但是不够快,allocator为默认的分配器安全比较高效;
    

原文地址:https://www.cnblogs.com/haomiao/p/11647200.html

时间: 2024-10-08 18:16:02

SGI-STL简记(一)-内存分配器解析的相关文章

STL中的内存分配器原理

题记:内存管理一直是C/C++程序的红灯区.关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面,很多C/C++书籍中都使用技巧的介绍.另一类是内存管理的实现,如linux内核的slab分配器,STL中的allocator实现,以及一些特定于某种对象的内存管理等.最近阅读了一些内存管理实现方面的资料和源码,整理了一下,汇编成一个系列介绍一些常用的内存管理策略. 1. STL容器简介 STL提供

[转]STL的内存分配器

题记:内存管理一直是C/C++程序的红灯区.关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面,很多C/C++书籍中都使用技巧的介绍.另一类是内存管理的实现,如linux内核的slab分配器,STL中的allocator实现,以及一些特定于某种对象的内存管理等.最近阅读了一些内存管理实现方面的资料和源码,整理了一下,汇编成一个系列介绍一些常用的内存管理策略. 1. STL容器简介 STL提供

SGI STL内存管理

在SGI STL版本的内存管理中,使用这样一种方式来分配内存:内存分配+对象初始化.首先是分配内存,其次是根据对象的类型(是否为POD[Plain of Data])来使用最有效的方式来初始化对象.回收内存也是用同样的方式:析构对象+回收内存,根据对象是否为POD类型,确定最有效的析构方式. SGI STL使用双层级配置器,第一级配置器直接使用malloc()和free(),第二级根据如下策略:当配置区块>128 Bytes时,视之为"足够大",调用一级配置器,否则视之为过小,调

STL的内存分配器

题记:内存管理一直是C/C++程序的红灯区.关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面,很多C/C++书籍中都使用技巧的介绍.另一类是内存管理的实现,如linux内核的slab分配器,STL中的allocator实现,以及一些特定于某种对象的内存管理等.最近阅读了一些内存管理实现方面的资料和源码,整理了一下,汇编成一个系列介绍一些常用的内存管理策略. 1. STL容器简介 STL提供

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

SGI设计了双层级配置器,第一级配置器直接使用malloc()和free(),第二级配置器则视情况采用不同的策略:当配置区块超过128bytes时,视之为“足够大”,便调用第一级配置器:当配置区小于128bytes时,视之为“过小”,为了降低额外负担,便采用复杂的memory pool 整理方式,而不再求助于第一级配置器.整个设计究竟只开放第一级配置器,取决于_USE_MALLOC是否被定义: 1 #ifdef __USE_MALLOC 2 ... 3 typedef __malloc_allo

SGI STL内存配置器(一):内存泄漏?

阅读了Alexander大神的SGI STL源码,膜拜,很高质量的源码,获益匪浅.温故而知新!下文中所有STL如无特殊说明均指SGI版本实现. STL 内存配置器 STL对内存管理最核心部分我觉得是它将C++对象创建过程分解为构造.析构和内存分配.释放!摆脱了由于频繁调用new或malloc函数向操作系统申请空间而造成的低效.其中析构操作时对具有non-trival.trival 析构函数的class区别对待也提高了效率.至于SGI的两级配置器结构则属于锦上添花的类型. STL两级结构的内存配置

STL源码剖析-配置器(内存分配器)

全局的构造和析构函数: template <class _T1, class _T2> inline void _Construct(_T1* __p, const _T2& __value) { new ((void*) __p) _T1(__value); placement new运算符:在已分配的内存上构造函数对象.opreator new ,new opreator,placement new区别请<a target=_blank href="http://w

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

一.前言 在STL中,容器是其中的重中之重,基本的STL中的算法,仿函数等都是围绕着容器实现的功能.而,内存配置器,是容器的实现的基础.所以,我第一次要去编写便是内存配置器的实现.在STL中,内存配置器的实现是在stl_alloc.h中. 二.配置器原理简要介绍 在SGI STL中配置分为两级,第一级配置器和第二级配置器.两者关系如下: 图1:第一级配置器和第二级配置器 在SGI STL中内存的配置器分为两级,第一级配置器和第二级配置器.第一级配置器就是,直接调用系统的malloc分配内存.对于

内存分配器 (Memory Allocator)

对于大多数开发者而言,系统的内存分配就是一个黑盒子,就是几个API的调用.有你就给我,没有我就想别的办法.来UC前,我就是这样认为的.实际深入进去时,才发现这个领域里也是百家争鸣,非常热闹.有操作系统层面的内存分配器(Memory Allocator),有应用程序层面的,有为实时系统设计的,有为服务程序设计的.但他们的目的确认一样的,平衡内存分配的性能和提高内存使用的效率. 从浏览器开发的角度看,手机内存的增长速度相对于网页内容的增长仍然只是温暖水平,像Android这样的用内存大户更要算计着用