首页 > 其他分享 >allocator分配器

allocator分配器

时间:2023-06-21 20:45:09浏览次数:26  
标签:__ Obj bytes list free 分配器 allocator size

  • 示意图

  • stl源码

// 摘自gcc-2.95.1

union _Obj {
    union _Obj* _M_free_list_link;
    char _M_client_data[1];    /* The client sees this.        */
};

# ifndef __SUNPRO_CC
    enum {_ALIGN = 8};
    enum {_MAX_BYTES = 128};
    enum {_NFREELISTS = _MAX_BYTES/_ALIGN};
# endif  
// 传入bytes字节,返回(bytes + 7)/7字节,即bytes除8向上取整。
static size_t _S_freelist_index(size_t __bytes) 
{
    return (((__bytes) + _ALIGN-1)/_ALIGN - 1);
}
// 传入bytes字节,返回bytes + 7 - (bytes + 7)% 7,即所需要的8字节的整数倍。
static size_t _S_round_up(size_t __bytes)
{ 
	return (((__bytes) + _ALIGN-1) & ~(_ALIGN - 1)); 
}
// 分配空间的函数
static void* allocate(size_t __n)
{
	// 存储指针的链表,指针指向实际存储空间。
	_Obj* __VOLATILE* __my_free_list;
    _Obj* __RESTRICT __result;
	// 如果需要分配的字节大于128字节,直接调用malloc
    if (__n > (size_t) _MAX_BYTES) {
        return(malloc_alloc::allocate(__n));
    }
    // 找到链表指定下标的指针
    __my_free_list = _S_free_list + _S_freelist_index(__n);
    // Acquire the lock here with a constructor call.
    // This ensures that it is released in exit or during stack
    // unwinding.
#       ifndef _NOTHREADS
        /*REFERENCED*/
        _Lock __lock_instance;
#       endif
	// 取出指定指针的指针,默认为0
    __result = *__my_free_list;
    if (__result == 0) {
	    // 如果指针为空,调用分配空间的函数,返回指向头节点的指针
        void* __r = _S_refill(_S_round_up(__n));
        return __r;
    }
    *__my_free_list = __result -> _M_free_list_link;
    return (__result);
}
  
template <bool __threads, int __inst>
void*
__default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
{
    int __nobjs = 20;
    // 将分配的空间分为20个大小为_n字节的节点
    char* __chunk = _S_chunk_alloc(__n, __nobjs);
    _Obj* __VOLATILE* __my_free_list;
    _Obj* __result;
    _Obj* __current_obj;
    _Obj* __next_obj;
    int __i;
	// 当指向空闲链表的头节点时
    if (1 == __nobjs) return(__chunk);
    __my_free_list = _S_free_list + _S_freelist_index(__n);

    /* Build free list in chunk */
      __result = (_Obj*)__chunk;
      *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
      for (__i = 1; ; __i++) {
        __current_obj = __next_obj;
        __next_obj = (_Obj*)((char*)__next_obj + __n);
        if (__nobjs - 1 == __i) {
            __current_obj -> _M_free_list_link = 0;
            break;
        } else {
            __current_obj -> _M_free_list_link = __next_obj;
        }
      }
    return(__result);
}

template <bool __threads, int __inst>
char*
__default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size,
                                                            int& __nobjs)
{
    char* __result;
    size_t __total_bytes = __size * __nobjs;
    size_t __bytes_left = _S_end_free - _S_start_free;

    if (__bytes_left >= __total_bytes) {
        __result = _S_start_free;
        _S_start_free += __total_bytes;
        return(__result);
    } else if (__bytes_left >= __size) {
        __nobjs = (int)(__bytes_left/__size);
        __total_bytes = __size * __nobjs;
        __result = _S_start_free;
        _S_start_free += __total_bytes;
        return(__result);
    } else {
        size_t __bytes_to_get =
      2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
        // Try to make use of the left-over piece.
        if (__bytes_left > 0) {
            _Obj* __VOLATILE* __my_free_list =
                        _S_free_list + _S_freelist_index(__bytes_left);

            ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
            *__my_free_list = (_Obj*)_S_start_free;
        }
        _S_start_free = (char*)malloc(__bytes_to_get);
        if (0 == _S_start_free) {
            size_t __i;
            _Obj* __VOLATILE* __my_free_list;
        _Obj* __p;
            // Try to make do with what we have.  That can't
            // hurt.  We do not try smaller requests, since that tends
            // to result in disaster on multi-process machines.
            for (__i = __size; __i <= _MAX_BYTES; __i += _ALIGN) {
                __my_free_list = _S_free_list + _S_freelist_index(__i);
                __p = *__my_free_list;
                if (0 != __p) {
                    *__my_free_list = __p -> _M_free_list_link;
                    _S_start_free = (char*)__p;
                    _S_end_free = _S_start_free + __i;
                    return(_S_chunk_alloc(__size, __nobjs));
                    // Any leftover piece will eventually make it to the
                    // right free list.
                }
            }
        _S_end_free = 0;    // In case of exception.
            _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
            // This should either throw an
            // exception or remedy the situation.  Thus we assume it
            // succeeded.
        }
        _S_heap_size += __bytes_to_get;
        _S_end_free = _S_start_free + __bytes_to_get;
        return(_S_chunk_alloc(__size, __nobjs));
    }
}

标签:__,Obj,bytes,list,free,分配器,allocator,size
From: https://www.cnblogs.com/skycrash/p/17494183.html

相关文章

  • 侯捷老师-内存管理和内存分配器
    目录链接:https://www.youtube.com/watch?v=uQ3wKWGmtk0&list=PLRTJhCIMo8HPlzVfZ8uxs6SGSSAtKXQ6Q所有的内存分配最终都会调用mallocglibc就是直接用的DLMalloc调用层次:c++程序员=>标准库容器std::allocator=>标准c++的operatornew()=>CRT的malloc和free=>操作......
  • slab分配器正式被弃用,slub成为分配器唯一选择
    在使用slab分配器进行内存分配时,可能会出现以下缺点:内存碎片化。由于slab分配器需要将内存分成大小相同的块,如果分配不均衡或者对象大小不同,就容易导致内存碎片化。性能下降。Slab分配器将内存分成不同的缓存区,每个缓存区都有自己的对象池。因此,当需要分配内存时,需要先找到合适......
  • 【C++11新特性】allocator空间配置类
    原文链接: http://blog.csdn.net/Xiejingfa/article/details/50955295今天我们来讲讲C++的allocator类。C++提供了new和delete操作符来管理动态内存空间。new操作通常需要完成两部分工作:一是在系统中申请内存空间,二是在分配的内存上构造对象。delete操作也通常需要完成对应的两......
  • 一路输入四路输出四进四出模拟信号隔离分配器0-5V/0-10V/1-5V转0-10mA/0-20mA/4-20mA
    主要特性:>>精度等级:0.1级、0.2级。产品出厂前已检验校正,用户可以直接使用>>辅助电源:5V/12V/15V/24VDC(范围±10%)>>国际标准一路信号输入:0-5V/0-10V/1-5V,0-10mA/0-20mA/4-20mA等>>四路输出标准信号:0-5V/0-10V/1-5V,0-10mA/0-20mA/4-20mA等,具有高负载能力>>全量程范围内极高的线性......
  • 12 Linux的伙伴系统和SLAB分配器
    伙伴系统: buddy物理内存页面管理算法,最先源自Sun公司的Solaris操作系统;Linux后来也引入了伙伴系统;表示一个物理内存页面:Linux定义了一个page结构体,大量使用了c的union联合体定义结构字段,其大小取决于结构体里面占用内存最大的变量决定;好处是信息量很多,占用内存很少;一个page......
  • C++ Allocator
    C++Allocator该开始搞项目了,但是在搞项目之前,先搞一下C++的Allocator,因为项目中会用到。现在还不确定到底模仿哪个,jemalloc和tcmalloc,先看看吧。1.为什么需要Allocator其实和new/delete是等价的,但是可以屏蔽一些底层细节,因为不一定所有平台都提供统一的内存分配方式,所以需要......
  • NCNN的内存显存分配器ncnn::Allocator & ncnn::VkAllocator翻译及其差异对比的学习笔
    NCNN的内存分配器ncnn::Allocator通用内存分配器 ncnn::PoolAllocator内存池分配器可以设置池大小,减少分配内存和析构内存次数,空间换时间 ncnn::UnlockedPoolAl......
  • CPP内存分配的详细指南——new和allocator以及智能指针
    Motivationcpp里面的内存管理一直让我头疼万分,最近重新翻了翻cppprimeplus这本书,被里面各种new搞得头皮发麻,于是就有了这篇博文。主要记录我自己对cpp里面内存管理的问......
  • 内存分配器对比
    ptmallocptmalloc是glibc默认的内存管理器tcmalloctcmalloc是Google开源的一个内存管理库,作为glibcmalloc的替代品。目前已经在chrome、safari等知名软件中运用对于小......
  • [C++]LeetCode 2502 设计内存分配器
    [C++]LeetCode2502.设计内存分配器题目描述Difficulty:中等RelatedTopics:设计,数组,哈希表,模拟给你一个整数n,表示下标从0开始的内存数组的大小。所有内存......