跳至主要內容

内存池allocate分配过程

张威大约 2 分钟c/c++SGI STL源码

内存池allocate分配过程

根据想分配的内存大小,先定位到_S_free_list 相应的元素__my_free_list(总共16个元素)

  • 如果__my_free_list下没有挂着空闲的chunk块,那直接从备用内存或者使用malloc申请chunk块,然后分配空间

  • 如果还有空闲的chunk块,那就使得_S_free_list 相应的元素指向__my_free_list下面挂着的下一块空闲的内存块,然后把前一块内存分配出去

template <bool threads, int inst>
class __default_alloc_template {
	//...
    class _Lock;
    friend class _Lock;
    class _Lock {	//出作用域自动解锁
        public:
            _Lock() { __NODE_ALLOCATOR_LOCK; }	//构造函数加锁
            ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }	//析构函数解锁
    };
  
    
  	/* __n must be > 0      */
  	static void* allocate(size_t __n)
  	{
    	void* __ret = 0;

      	if (__n > (size_t) _MAX_BYTES) {	//enum {_MAX_BYTES = 128};
      		//超过128字节,使用一级空间配置器,底层malloc方法开辟内存
            __ret = malloc_alloc::allocate(__n);	
    	}
    	else {	//小于128则通过内存池管理
            //定义一个指针指向__n个字节应该在内存池哪个块分配
      		_Obj* __STL_VOLATILE* __my_free_list
          		= _S_free_list + _S_freelist_index(__n);

#ifndef _NOTHREADS
            //对于自由链表的增删改要加锁,不是线程安全的
      		_Lock __lock_instance;
#endif
        	//result为第一个chunk块地址
      		_Obj* __RESTRICT __result = *__my_free_list;
      		if (__result == 0)
                //若__result下没有挂着空闲的chunk块,
                //_S_refill直接构造chunk后分配,
                //_S_round_up(__n)指的是内存池每个块的大小,
        		__ret = _S_refill(_S_round_up(__n));
      		else {//如果不为空,则ret指向链表的第一个节点
                //因为第一个chunk块要被分配出去了,
                //也就是_S_free_list的元素直接指向后面的节点
        		*__my_free_list = __result -> _M_free_list_link;
        		__ret = __result;// 这时候是要把__result分配出去
      		}
    	}

    	return __ret;
  	};
};