• STL内存分配


    STL内存创建

    Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu  转载请标明来源 

    1.      Stl内存创建基类模板__malloc_alloc_template

    STL的经常使用的内存创建參考文件: stl_alloc.h,文件里定义了__malloc_alloc_template模板库,创建与释放使用C方法mallocfreerealloc,模板库里面主要对外提供了函数:

    allocate: 分配内存

    deallocate: 释放内存

    reallocate: 又一次分配内存

    __set_malloc_handler: 设置异常处理函数

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

        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;

      }

     

      static void (* __set_malloc_handler(void (*__f)()))()

      {

        void (* __old)() = __malloc_alloc_oom_handler;

        __malloc_alloc_oom_handler = __f;

        return(__old);

      }

     

    };

     

    2.   内存分配与释放

    使用mallocrealloc分配内存,对于分配内存异常的处理,模板库中交给内部的这两个静态方法:

    _S_oom_malloc

    _S_oom_ realloc

    使用free释放内存,对于释放内存来说,是无异常处理的,直接调用free指针,传入的size_t未使用。

    3   分配异常处理

    分配内存的异常处理方法,參考_S_oom_malloc/_S_oom_realloc中的实现

    在实现中或者是通过抛出异常,或者是通过运行约定的处理函数(如内存整理函数),然后继续申请内存。

    在以下的函数中,涉及了函数指针:

    __malloc_alloc_oom_handler

    这个函数指定方法__malloc_alloc_template ::__set_malloc_handler

    假设这个函数未指定的话,调用异常__THROW_BAD_ALLOC处理

    a.   C++下,抛出std::bad_alloc(),

    b.   C下,向标准输出中打印并终止程序: fprintf(stderr, "out of memory "); exit(1)

    假设这个函数指定的话,指行这个函数(比如内存整理函数),然后再次申请内存,直到成功申请到后返回申请到的内存地址:

    __my_malloc_handler = __malloc_alloc_oom_handler;

    (*__my_malloc_handler)();

    __result = malloc(__n);

    if (__result) return(__result);

     

    #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

    #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 (;;) {

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

        }

    }

    4.   封装的几组分配方式

    a.   Simple_alloc,附加了检查0/NULL的操作

    template<class _Tp, class _Alloc>

    class simple_alloc {

    public:

        static _Tp* allocate(size_t __n)

          { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }

        static _Tp* allocate(void)

          { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }

        static void deallocate(_Tp* __p, size_t __n)

          { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }

        static void deallocate(_Tp* __p)

          { _Alloc::deallocate(__p, sizeof (_Tp)); }

    };

    b.   debug_alloc每次分配时,多附加8字节的空间,用于存储当前分配的size大小。

    // Allocator adaptor to check size arguments for debugging.

    // Reports errors using assert.  Checking can be disabled with

    // NDEBUG, but it's far better to just use the underlying allocator

    // instead when no checking is desired.

    // There is some evidence that this can confuse Purify.

    template <class _Alloc>

    class debug_alloc {

    private:

      enum {_S_extra = 8};  // Size of space used to store size.  Note

                            // that this must be large enough to preserve

                            // alignment.

    public:

      static void* allocate(size_t __n)

      {

        char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);

        *(size_t*)__result = __n;

        return __result + (int) _S_extra;

      }

      static void deallocate(void* __p, size_t __n)

      {

        char* __real_p = (char*)__p - (int) _S_extra;

        assert(*(size_t*)__real_p == __n);

        _Alloc::deallocate(__real_p, __n + (int) _S_extra);

      }

      static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)

      {

        char* __real_p = (char*)__p - (int) _S_extra;

        assert(*(size_t*)__real_p == __old_sz);

        char* __result = (char*)

          _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,

                                       __new_sz + (int) _S_extra);

        *(size_t*)__result = __new_sz;

        return __result + (int) _S_extra;

      }

    };

    5.   内存分配类allocator/__allocator

    allocator分配类使用缺省的分配类(alloc),使用分配类的静态方法。

    __allocator类须要输入分配类,并对分配类实例化了对像,调用对像的分配方法分配内存。

    a)   allocator

    // This implements allocators as specified in the C++ standard. 

    //

    // Note that standard-conforming allocators use many language features

    // that are not yet widely implemented.  In particular, they rely on

    // member templates, partial specialization, partial ordering of function

    // templates, the typename keyword, and the use of the template keyword

    // to refer to a template member of a dependent type.

    #ifdef __STL_USE_STD_ALLOCATORS

    template <class _Tp>

    class allocator {

      typedef alloc _Alloc;          // The underlying allocator.

    public:

      typedef size_t     size_type;

      typedef ptrdiff_t  difference_type;

      typedef _Tp*       pointer;

      typedef const _Tp* const_pointer;

      typedef _Tp&       reference;

      typedef const _Tp& const_reference;

      typedef _Tp        value_type;

      template <class _Tp1> struct rebind {

        typedef allocator<_Tp1> other;

      };

      allocator() __STL_NOTHROW {}

      allocator(const allocator&) __STL_NOTHROW {}

      template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}

      ~allocator() __STL_NOTHROW {}

      pointer address(reference __x) const { return &__x; }

      const_pointer address(const_reference __x) const { return &__x; }

      // __n is permitted to be 0.  The C++ standard says nothing about what

      // the return value is when __n == 0.

      _Tp* allocate(size_type __n, const void* = 0) {

        return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp)))

                        : 0;

      }

      // __p is not permitted to be a null pointer.

      void deallocate(pointer __p, size_type __n)

        { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }

      size_type max_size() const __STL_NOTHROW

        { return size_t(-1) / sizeof(_Tp); }

      void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

      void destroy(pointer __p) { __p->~_Tp(); }

    };

     

    b)   __allocator

    能够传入不同的分配方式,另外实例化了对像,支持对象内记录分配字节等,属于对复杂分配方式的支的。

    __allocator最大的特点,实例化了分配对像

    // Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)

    // into a standard-conforming allocator.   Note that this adaptor does

    // *not* assume that all objects of the underlying alloc class are

    // identical, nor does it assume that all of the underlying alloc's

    // member functions are static member functions.  Note, also, that

    // __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.

    template <class _Tp, class _Alloc>

    struct __allocator {

      _Alloc __underlying_alloc;

      typedef size_t    size_type;

      typedef ptrdiff_t difference_type;

      typedef _Tp*       pointer;

      typedef const _Tp* const_pointer;

      typedef _Tp&       reference;

      typedef const _Tp& const_reference;

      typedef _Tp        value_type;

      template <class _Tp1> struct rebind {

        typedef __allocator<_Tp1, _Alloc> other;

      };

      __allocator() __STL_NOTHROW {}

      __allocator(const __allocator& __a) __STL_NOTHROW

        : __underlying_alloc(__a.__underlying_alloc) {}

      template <class _Tp1>

      __allocator(const __allocator<_Tp1, _Alloc>& __a) __STL_NOTHROW

        : __underlying_alloc(__a.__underlying_alloc) {}

      ~__allocator() __STL_NOTHROW {}

      pointer address(reference __x) const { return &__x; }

      const_pointer address(const_reference __x) const { return &__x; }

      // __n is permitted to be 0.

      _Tp* allocate(size_type __n, const void* = 0) {

        return __n != 0

            ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp)))

            : 0;

      }

      // __p is not permitted to be a null pointer.

      void deallocate(pointer __p, size_type __n)

        { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }

      size_type max_size() const __STL_NOTHROW

        { return size_t(-1) / sizeof(_Tp); }

      void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

      void destroy(pointer __p) { __p->~_Tp(); }

    };

    6.   内存分配结构体

    这个结构体非常有意思,

    參数一: _S_instanceless标识包括有allocator_type定义

    參数二: _Alloc_type,简单分配方式,simple_alloc调用_Alloc的静态方法进行分配释放内存

    參数三:  allocator_type,可支持复杂分配方式,实例化了_Alloc对像,使用对象方法分配释放内存,支持对象内包括分配的总数,或其他附加信息,能够在对像内实现内存池等。

    template <class _Tp, class _Alloc>

    struct _Alloc_traits<_Tp, debug_alloc<_Alloc> >

    {

      static const bool _S_instanceless = true;

      typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;

      typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;

    };

  • 相关阅读:
    2017年3月笔记
    2017年2月笔记
    2017年1月笔记
    2016年12月笔记
    2016年11月笔记
    2016年10月笔
    2016年9月笔记
    2016年8月笔记
    2016年7月笔记
    2016年6月笔记
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4329057.html
Copyright © 2020-2023  润新知