zoukankan      html  css  js  c++  java
  • STL源码分析之第一级配置器

    前言

    上一节我们分析了空间配置器对new的配置, 而STL将空间配置器分为了两级, 第一级是直接调用malloc分配空间, 调用free释放空间, 第二级三就是建立一个内存池, 小于128字节的申请都直接在内存池申请, 不直接调用mallocfree.

    本节我们就先分析第一种空间配置器, 直接调用malloc, free, 而STL有是怎样的封装处理.

    一级配置器

    一级配置器的类. 它无template型别参数. 这里我将public定义的函数和私有成员函数成对分离出来讲解.

    // 一级配置器
    template <int inst>
    class __malloc_alloc_template 
    {
      // 这里private里面的函数都是在内存不足的时候进行调用的
      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)();   // 内存不足设置的处理例程, 默认设置的是0, 表示没有设置处理例程, 这个处理例程是由用户手动设置的
    #endif
      public:
    };
    

    唯一比较麻烦的就是set_malloc_handler 它就是接受一个函数指针, 用来保存用户自定义的处理函数, 如果用户没有设置的话, 默认就设置为0. 因为处理函数会跟后面的内存不足有关系.

    // 这里是模仿c++的set_new_handler. 是由用户自己定义的处理函数, 没有设置默认为0
    static void (* set_malloc_handler(void (*f)()))()
    {
          void (* old)() = __malloc_alloc_oom_handler;
          __malloc_alloc_oom_handler = f;
          return(old);
    }
    

    默认将处理例程设置为0, 只有用户自己设置.

    template <int inst>
    void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
    

    allocate

    allocate : 很明显, 这里直接调用malloc分配内存, 当内存不足的时候, 程序继续调用oom_malloc来选择抛出异常还是一直申请内存, 直到申请内存成功.

    // 在分配和再次分配中, 都会检查内存不足, 在不足的时候直接调用private中相应的函数
    static void * allocate(size_t n)
    {
          void *result = malloc(n);
          if (0 == result) result = oom_malloc(n);
          return result;
    }
    

    oom_malloc函数功能 : 除非用户自定义了处理例程, 否则当内存不足的时候直接输出内存不足的提示然后直接调用exit(1);
    用户定义了处理程序, 函数会一直进行内存申请, 直到申请到内存为止

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

    deallocate

    一级配置器直接调用free释放内存

    static void deallocate(void *p, size_t /* n */)
    {
          free(p);
    }
    

    reallocate

    下面的函数都是很简单的或是重复的功能, 就一笔带过.

    这里reallocate和oom_realloc和上面allocate一样的, 这里就不做过多的解释了.

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

    程序默认定义mallo_alloc函数, 并且设置统一的调用接口, 默认的的接口为第二级配置器

    // 默认将malloc_alloc设为0;
    typedef __malloc_alloc_template<0> malloc_alloc;
    

    统一的接口

    定义符合STL规格的配置器接口, 不管是一级配置器还是二级配置器都是使用这个接口进行分配的

    // 定义符合STL规格的配置器接口, 不管是一级配置器还是二级配置器都是使用这个接口进行分配的
    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)); }
    };
    

    总结

    本节对STL的第一级配置器做了分析, STL对malloc和free用函数重新进行了封装, 同时一级还是二级都做了统一的接口. 接下来我们继续分析第二级配置器.

  • 相关阅读:
    全球化编码
    linuxGrep命令
    Xcode-插件所在路径
    多控制器间数据传递
    触摸事件
    IOS事件处理
    事件监听的三种方法
    UITabBarController
    聊天布局
    Info.plist:项目配置文件
  • 原文地址:https://www.cnblogs.com/0xfffffff0/p/10078542.html
Copyright © 2011-2022 走看看