SGISTL源码阅读一 空间配置器上(第一级配置器__malloc_alloc_template)

SGISTL源码阅读一 空间配置器上(第一级配置器__malloc_alloc_template)

引入

我们所熟知的C++内存配置操作一般为

class A {}
A* pa = new A();  	//1.分配内存 2.构造对象
delete pa;			//1.对象析构 2.释放内存

其中new完成了两个操作
1.调用operator new配置内存
2.调用A::A()构造对象

这样做没有考虑到任何效率上的强化,如果有些空间根本不会被用到,那么构造对象完全就是一种浪费。
而STL中的alloc将new所完成的操作拆分开来,SGISTL源码中有两个文件,stl_alloc.h负责内存空间的配置与释放,stl_construct.h负责对象内容的构造与析构。

SGI特殊的空间配置器

对象构造前的空间配置和对象析构后的空间释放,由stl_alloc.h负责。
考虑到小型区块可能造成的内存破碎问题,SGI设计了双层级配置器。
第一级配置器用于处理大于128bytes的情况,即申请大的内存,第二级配置器用于申请小内存。

第一级配置器(__malloc_alloc_template)

直接使用malloc()free()即可,我们来深入源码探究。

//这里用到了模板全特化技术
template <int inst>
class __malloc_alloc_template {
    private:
    /*
     *oom(out of memory)
     *下面的函数用于处理内存不足的情况
     */
    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:
    //申请n个大小的空间
    static void * allocate(size_t n)
    {
        void *result = malloc(n);
        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);
        if (0 == result) result = oom_realloc(p, new_sz);
        return result;
    }
    /*
     *这是一个返回值为函数指针的指针函数(传送门:https://blog.csdn.net/lyn_00/article/details/83549655)
     *仿真C++的set_new_handler()
     *它的作用是可以让用户自己定义内存不足时的处理函数,并返回旧的处理方法
     */
    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;
    
	/*
     *如果用户没有定义内存不足时的处理函数,则抛出一个异常,反之,则申请到内存正常退出
     *我们可以注意到这是一个死循环,但是也不难理解,因为必须对内存不足这种情况做好处理
     */
    for (;;) {
        my_malloc_handler = __malloc_alloc_oom_handler;
        if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
        (*my_malloc_handler)();
        result = malloc(n);
        if (result) return(result);
    }
}

//realloc和malloc类似
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);
    }
}
//直接将参数inst指定为0
typedef __malloc_alloc_template<0> malloc_alloc;
总结

以上主要对SGI中空间配置器的第一级配置器进行了分析。它如何申请释放内存,以及对内存不足时的处理。第二级配置器比第一级配置器要复杂得多,将会在下一篇博客中介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值