C++空间配置器详解

一、C++对象创建的过程

比如以下的代码

class Foo{
};
Foo *pf = new Foo();//配置内存,然后构造对象
delete pf;//将对象析构,然后释放内存

new算式包含两个阶段

  • 调用::operator new 配置内存。
  • 调用Foo::Foo()构造对象的内容。

delete算式包含两个阶段

  • 调用Foo::~Foo()将对象析构。
  • 调用::operator delete 释放内存。

二、SGI标准的空间配置器 std::allocator

下面是SGI标准的空间配置器 std::allocator的源码,这里的allocator 只是基层内存配置/释放行为的一层简单的包装,并没有效率上的优化。

template 
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 
inline void deallocate(T* buffer) {
    ::operator delete(buffer);
}

template 
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))); 
    }
};

class allocator {
public:
    typedef void* pointer;
};

三、SGI特殊的空间配置器 std::alloc

STL allocator将new算式以及delete算式的两个阶段的操作分开。内存配置操作由alloc::allocate()负责,内存释放由alloc::deallocate()负责;对象构造由::construct()负责,对象析构由::destrory()负责。
空间配置器的包装类simple_alloc

  • 可指定配置一级或者二级空间配置器
template
class simple_alloc {

public:
    static T *allocate(size_t n)
                { return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
    static T *allocate(void)
                { return (T*) Alloc::allocate(sizeof (T)); }
    static void deallocate(T *p, size_t n)
                { if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
    static void deallocate(T *p)
                { Alloc::deallocate(p, sizeof (T)); }
};

一级空间配置器源码

template 
class __malloc_alloc_template 
{
private:

static void *oom_malloc(size_t);

static void *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);

    //分配内存失败,调用oom_malloc尝试分配所需内存
    if (0 == result) 
        result = 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);

    //分配内存失败,调用oom_realloc尝试分配所需内存
    if (0 == result) 
        result = oom_realloc(p, new_sz);
    
    return result;
}

//模拟C++标准的std::set_new_handle全局函数设置内存分配失败后的处理例程
static void (* set_malloc_handler(void (*f)()))()
{
    //保存旧的处理例程
    void (* old)() = __malloc_alloc_oom_handler;

    //设置新的处理例程
    __malloc_alloc_oom_handler = f;

    //返回旧的处理例程
    return(old);
}

};

// malloc_alloc out-of-memory handling
#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
template 
void (* __malloc_alloc_template::__malloc_alloc_oom_handler)() = 0;
#endif

template 
void * __malloc_alloc_template::oom_malloc(size_t n)
{
    void (* my_malloc_handler)();
    void *result;

    //此循环只在两种情形下才会返回
    //1. 没有设置内存分配失败后的处理例程
    //2. 重新利用malloc尝试分配内存成功
    for (;;) 
    {
        my_malloc_handler = __malloc_alloc_oom_handler;
        
        if (0 == my_malloc_handler) 
        { 
          __THROW_BAD_ALLOC; 
        }
        
        (*my_malloc_handler)(); //调用内存分配失败后设置的处理例程,参见Effective C++
        
        result = malloc(n);
        
        if (result) 
            return(result);
    }
}


template 
void * __malloc_alloc_template::oom_realloc(void *p, size_t n)
{
    void (* my_malloc_handler)();
    void *result;

    for (;;) 
    {
        my_malloc_handler = __malloc_alloc_oom_handler;
        
        if (0 == my_malloc_handler) 
        { 
          __THROW_BAD_ALLOC; 
        }
        
        (*my_malloc_handler)();
        
        result = realloc(p, n);
        
        if (result) 
            return(result);
    }
}

typedef __malloc_alloc_template<0> malloc_alloc;

二级空间配置器源码
https://blog.csdn.net/wenqian1991/article/details/19605727
https://blog.csdn.net/dandelion_gong/article/details/51353918

参考

《C++ 内存分配(new,operator new)详解)》
https://blog.csdn.net/wudaijun/article/details/9273339

你可能感兴趣的:(C++空间配置器详解)