STL源码分析:空间配置器浅析

       

目录

allocator

alloc

一级配置器

二级配置器

自由链表

内存分配allocate

_S_refill函数

_S_chunk_alloc函数

内存释放deallocate

为什么要使用free_list?

为什么free_list要把128bytes分成16部分?


对于一些容器如vector、map、set之类的,都需要一个模板参数Alloc,用来指定一个空间配置器,这个配置器的作用,就是管理内存的分配和释放。在SGI STL中,提供了默认的配置器,这也是为什么我们在创建一个vector、map的时候不需要传入第二个参数。以vector为例,其头部定义如下:

template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class vector : protected _Vector_base<_Tp, _Alloc> 
{...}

       这里指定了一个默认的配置器参数, __STL_DEFAULT_ALLOCATOR(_Tp)。 这是一个宏,它有两种情况:

# ifndef __STL_DEFAULT_ALLOCATOR
#   ifdef __STL_USE_STD_ALLOCATORS
#     define __STL_DEFAULT_ALLOCATOR(T) allocator< T >
#   else
#     define __STL_DEFAULT_ALLOCATOR(T) alloc
#   endif
# endif

      也就是说,默认的配置器要么是allocator,要么就是alloc。

allocator

      当然这里的allocator并不是本文的重点,因为它只是把operator new和operator delete简单进行了封装,如下所示:

template <class T>
inline T* allocate(ptrdiff_t size, T*) {//进行内存的分配,并且返回分配内存的首地址
    set_new_handler(0);
    T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
    if (tmp == 0) {
	cerr << "out of memory" << endl; 
	exit(1);
    }
    return tmp;
}


template <class T>
inline void deallocate(T* buffer) {//delete释放资源
    ::operator delete(buffer);
}

template <class T>
class allocator {
public:
    typedef T value_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    pointer allocate(size_type n) { 
	return ::allocate((difference_type)n, (pointer)0);
    }
    void deallocate(pointer p) { ::deallocate(p); }
    pointer address(reference x) { return (pointer)&x; }
    const_pointer const_address(const_reference x) { 
	return (const_pointer)&x; 
    }
    size_type init_page_size() { 
	return max(size_type(1), size_type(4096/sizeof(T))); 
    }
    size_type max_size() const { 
	return max(size_type(1), size_type(UINT_MAX/sizeof(T))); 
    }
};

       allocator的内容很简单,下面着重来看看alloc。

alloc

        alloc是一个经过typedef定义的新类型,其定义如下:

typedef __malloc_alloc_template<0> malloc_alloc;

# ifdef __USE_MALLOC

typedef malloc_alloc alloc;
...
#else typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
...
#endif

       从这里可以看到,alloc的类型实际上是由__USE_MALLOC这个宏来定义的,如果定义了,那么alloc使用的就是__malloc_alloc_template,否则就是__default_alloc_template。

       这两个都是类,前者就是一级配置器,后者是二级配置器。二者都包含了基本的内存分配、内存释放等函数。

一级配置器

       一级配置器是__malloc_alloc_template类,其定义如下:

template <int __inst>
class __malloc_alloc_template {

private:

  static void* _S_oom_malloc(size_t);
  static void* _S_oom_realloc(void*, size_t);

#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  static void (* __malloc_alloc_oom_handler)();
#endif

public:

  static void* allocate(size_t __n)
  {
    void* __result = malloc(__n); //直接用malloc进行分配,如果分配失败调用_S_oom_mallo
    if (0 == __result) __result = _S_oom_malloc(__n);
    return __result;
  }

  static void deallocate(void* __p, size_t /* __n */)
  {
    free(__p); //释放
  }

  static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
  {
    void* __result = realloc(__p, __new_sz); //用realloc分配,分配失败调用_S_oom_realloc
    if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
    return __result;
  }

  static void (* __set_malloc_handler(void (*__f)()))()//设置异常捕捉函数,并且返回设之前老的捕捉函数
  {
    void (* __old)() = __malloc_alloc_oom_handler;
    __malloc_alloc_oom_handler = __f;
    return(__old);
  }

};

       一级配置器其实很简单,它内部的allocate、deallocate和reallocate函数实际上就是对malloc、free和realloc的简单封装,还提供了一个设置异常捕捉函数的接口__set_malloc_handler,这个函数的作用就是用传入的函数指针更新类静态变量函数指针__malloc_alloc_oom_handler并且返回更新前的__malloc_alloc_oom_handler。

       那么__malloc_alloc_oom_handler这个函数指针有什么用呢?

       在allocate和reallocate函数中,如果内存分配失败,就会调用相应的_S_oom_alloc和_S_oom_realloc,它们的定义如下:

template <int __inst>
void*
__malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
{
    void (* __my_malloc_handler)();
    void* __result;

    for (;;) {//循环调用malloc,直到分配成功,分配失败就调用异常捕捉函数
        __my_malloc_handler = __malloc_alloc_oom_handler;
        if (0 == __my_malloc_handler) { __THROW_
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值