美文网首页
C++空间配置器详解

C++空间配置器详解

作者: Catcher07 | 来源:发表于2018-07-21 21:16 被阅读0次

    一、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 <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) {
        ::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))); 
        }
    };
    
    class allocator<void> {
    public:
        typedef void* pointer;
    };
    

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

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

    • 可指定配置一级或者二级空间配置器
    template<class T, class Alloc>
    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 <int inst>
    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 <int inst>
    void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
    #endif
    
    template <int inst>
    void * __malloc_alloc_template<inst>::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 <int inst>
    void * __malloc_alloc_template<inst>::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++空间配置器详解

          本文链接:https://www.haomeiwen.com/subject/lsdkmftx.html