• STL初探——第一级配置器 __malloc_alloc_template的学习心得


      在第一级配置器中,一开始就定义了内存分配出错的宏接口,如下:

    #ifndef __THROW_BAD_ALLOC
    #  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
    #    include <stdio.h>
    #    include <stdlib.h>
    #    define __THROW_BAD_ALLOC fprintf(stderr, "out of memory
    "); exit(1)
    #  else /* Standard conforming out-of-memory handling */
    #    include <new>
    #    define __THROW_BAD_ALLOC throw std::bad_alloc()
    #  endif
    #endif

      先弄清楚第一级配置器如何工作,注意没有template型别参数,因为我们只是分配空间,并不进行对象的构造,至于非型别参数 "__inst" ,就没怎么派上用场,如下:

    template <int __inst>          
    class __malloc_alloc_template {
    
    private:                 
    //以下函数是处理内存不足的情况
      static void* _S_oom_malloc(size_t);
      static void* _S_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);       if (0 == __result) __result = _S_oom_malloc(__n); //分配的内存无法满足需求时,调用_S_oom_malloc()函数
        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 = _S_oom_realloc(__p, __new_sz);  
        return __result;
      }
      //你可以通过该函数指定自己的 out-of-memory 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>::_S_oom_malloc(size_t __n) { void (* __my_malloc_handler)(); void* __result; for (;;) {                                //和_S_oom_realloc类似                         __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); } } template <int __inst> void* __malloc_alloc_template<__inst>::_S_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); } }

      第一级配置器以 malloc()、free()、realloc()等 C 函数执行实际的内存配置、释放、重配置操作,并实现出类似 C++ new-handler 的机制,不过并不能直接使用 C++ new-handler 机制, 因为其并非使用 ::operator new 来配置内存。

      C++ new-handler 机制是,可以要求系统在配置需求无法被满足时,调用你所指定的函数。一旦 ::operator new 无法完成任务,在丢出 std::bad_alloc 异常状态之前,会先调用由客端指定的处理例程,该处理例程通常被称为new-handler。

      《effective C++ handler》 中介绍了 new-handler 的内存不足处理模式,详情见下篇。

      SGI 以malloc 而非 ::operator new 来配置内存,原因是C++并未提供相应于 realloc() 的内存配置操作,当然不排除还有些历史因素。因此,SGI 不能使用 C++ 的 set_new_handler() ,必需仿真一个类似类似的 set_new_handler().

      SGI 第一级配置器 allocate() 和 realloc() 都是在调用 malloc() 和 realloc() 不成功后,改调用 oom_malloc() 和 oom_realloc()。后两者都有死循环,不断调用 "内存不足处理例程" ,期望在某次调用的时候,能够得到充足的内存分配而完成任务。但如果“内存不足处理例程”并没有被客端设定, oom_malloc() 和 oom_realloc() 便会直接调用 __THROW_BAD_ALLOC,丢出 bad_alloc 异常信息,或利用 exit(1)终止程序。

      

    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    CSS
    CSS
    CSS
    CSS
    CSS
    CSS
    FLASK
    人物
    关于反射
    释放c盘空间
  • 原文地址:https://www.cnblogs.com/Forever-Road/p/6808442.html
Copyright © 2020-2023  润新知