STL学习_SGI空间配置器_第一级配置器源码分析

来源:互联网 发布:物竞化学品数据库 编辑:程序博客网 时间:2024/05/22 01:05
    这篇文章自己总结了下自己对于STL标准库中的SGI配置器的第一级配置器的源码分析,主要是想将自己上篇的理论知识具体化,#ifndef _STL_ALLOC1_H#define _STL_ALLOC1_H#include <iostream>#include <stdlib.h>#include <exception>#include <malloc.h>using namespace std;#if 1#include <new>#define __THROW_BAD_ALLOC cerr<<"Out of memory"<<endl;exit(1)#elif !defined(__THROW_BAD_ALLOC)#include <iostream.h>#define __THROW_BAD_ALLOC cerr<<"out of memory"<<endl;exit(1)#endiftemplate<int inst>class __malloc_alloc_template{private:    //以下函数用来处理内存不足的情况    static void *oom_malloc(size_t);    static void *oom_realloc(void *, size_t);    static void (*__malloc_alloc_oom_handler)();public:    static void *allocate(size_t n)    {        void *result;        result = malloc(n);        if(0 == result){            result = oom_malloc(n);        }        return result;    }    static void *reallocate(void *p, size_t, size_t new_sz)    {        void *result = realloc(p, new_sz);        if(0 == result){            result = oom_realloc(p, new_sz);        }        return result;    }    static void *deallocate(void *p, size_t)    {        free(p);    }    //设置异常处理函数    //SGI不能直接使用c++的set_new_handler()函数,必须仿真一个类似的set_malloc_handler()    //set_malloc_handler()这个函数传入的参数为[void (*f)()]是个函数指针,指的是下面写的程序test.cpp中    //的my_new_handler()这个函数    static void (*set_malloc_handler(void (*f)()))()    {        void (*old)() = __malloc_alloc_oom_handler;        __malloc_alloc_oom_handler = f;       return (old);    }};//这里将__malloc_alloc_oom_handler()设置为0,有待客户设置自己想要的异常处理函数。template<int inst>void (*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;//当allocate()申请空间失败的情况下会调用oom_malloc()这个函数,这个函数会不断的尝试空间的释放,//和客户空间的申请,如果客户自己定义了内存异常处理函数(my_malloc_handler())则当内存申请失败//会调用异常处理函数,如果客户没有自己定义异常处理函数,则抛出一个异常。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;//抛出一个异常,并利用exit(1)函数硬生生的终止程序        }        //如果设置了,则调用客户自己定义的异常处理函数        (*my_malloc_handler)();        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 = malloc(n);        if(0 == result){            return result;        }    }}typedef __malloc_alloc_template<0> malloc_alloc; #endif测试程序:#include "stl_alloc1.h"void my_new_handler(){    cout<<"out of memory"<<endl;}int main(int argc, char **argv){    __malloc_alloc_template<0>::set_malloc_handler(my_new_handler);    int *p = (int *)__malloc_alloc_template<0>::allocate(sizeof(int) * 10);    *p = 100;    cout<<*p<<endl;    __malloc_alloc_template<0>::deallocate(p, 0);    return 0;}申请的空间大小为4*10,结果系统能够给客户申请这么大的空间申请成功,如果改成sizeof(int)*100000000000000即申请一个很大的空间,系统就没有足够大的空间供客户申请,则由于malloc()申请不到空间,则会调用oom_alloc()函数,但是由于客户需求的空间太大oom_alloc()也申请不到空间,则oom_alloc()函数内部处于死循环阶段不断的调用异常处理函数my_new_handler(),不断的进行空间的申请,所以结果是屏幕上不断的打印out of memory

0 0