跳至主要內容

分配内存池_S_refill源码

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

分配内存池_S_refill源码

作用:

  1. 根据__n,在_S_free_list中对应位置的元素指向一个__nobjs(默认为20)个__n字节chunk块的内存池
  2. 并且把第一个__chunk块分配出去,并填写剩下所有__chunk块的next域。

只有从备用内存中分配出来,并挂在_S_free_list 下的,才会填写chunk块头的_M_free_list_link

template <bool __threads, int __inst>
void* __default_alloc_template<__threads, __inst>::_S_refill(size_t __n){
    int __nobjs = 20; // 局部变量,内存池中开辟__chunk 块的数量
    // 申请__nobjs个__n字节chunk的内存池,__nobjs按引用传入_S_chunk_alloc,__nobjs可能会在_S_chunk_alloc里被修改
    // 如果_S_start_free和_S_end_free之间的备用内存不够分配20个__n字节的chunk时,会修改__nobjs
    char* __chunk = _S_chunk_alloc(__n, __nobjs); 
    _Obj* __STL_VOLATILE* __my_free_list;// 二级指针,遍历_S_free_list数组
    _Obj* __result;
    _Obj* __current_obj;
    _Obj* __next_obj;
    int __i;

	// 当内存池最多只能包含1个__n字节chunk块的时候,直接返回,不需要进入for循环再填写next域
    if (1 == __nobjs) return(__chunk);       
    // _S_freelist_index(__n)返回的是分配的__n字节在_S_free_list的哪个元素中分配
    // __my_free_list 指向分配__n字节的元素
    __my_free_list = _S_free_list + _S_freelist_index(__n);

    /* Build free list in chunk */
      // 指向待分配出去的内存块
      __result = (_Obj*)__chunk; 

      // __chunk 是char*,实际上+__n就是越过了一个__chunk块,指向了第二个__chunk 块的起始地址
      // __next_obj 和*__my_free_list 都指向第二个块
      *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
      
      // i从1开始,表示__current_obj 一开始就指向第二个__chunk块
      // 整个for循环做的就是把内存是填写剩下所有__chunk块的next域 
      for (__i = 1; ; __i++) {
        __current_obj = __next_obj;
        __next_obj = (_Obj*)((char*)__next_obj + __n);
        
        //因为每循环依次__i都加1,最后一个下标__i为__nobjs-1
        if (__nobjs - 1 == __i) {
        	// next域填写完成,最后一个__chunk块的next域为0地址
            __current_obj -> _M_free_list_link = 0;
            break;
        } else {
            __current_obj -> _M_free_list_link = __next_obj;
        }
      }
    return(__result);
}