内存池——第一章 几种常用的内存池技术

几乎所有应用程序中都会有内存的分配和释放,而频繁的分配和释放内存无疑会产生内存碎片,降低系统性能,尤其对性能要求较高的程序比较明显。下面介绍几种常见的内存池技术。

    一  环形缓存

    环形缓存的基本原理如图:
    初始化状态(wpos_ = rpos_):

    写了部分数据,同时读了一部分数据(wpos_ > rpos_):

    wpos_写数据到尾部后,又从头开始,rpos_还读到尾部(wpos_ < rpos_):

    rpos_读了N(N>= 1)圈后,赶上了wpos_,也就是说没有数据可读了(wpos_ < rpos_):

   综合起来,看起来像这样子:

 需要注意的是:
    #1    wpos_ < rpos_的情况下,rpos_ 读数据一直读到尾部,然后又从头部开始,数据拼接一块即可;
    #2    如果 | wpos_ -  rpos |  < cnt,即没有足够的数据可来写的时候,需要重写分配内存,具体分配多少,根据你的程序来定,额外大小或者1.5倍原大小;
    部分实现代码如下:

点击(此处)折叠或打开

  1. #define EXTRA_BUFFER_SIZE        64

  2. namespace easy
  3. {
  4.     template<class _Type,class _Alloc >
  5.     class EasyRingbuffer 
  6.     {
  7.     public:
  8.         typedef _Alloc allocator_type;

  9.         explicit EasyRingbuffer(size_t size):
  10.         size_(size),
  11.             wpos_(0),
  12.             rpos_(0)
  13.         {
  14.             buffer_ = _allocate(size_);
  15.         }

  16.         ~EasyRingbuffer() { _deallocate(buffer_,size_); }

  17.         template<typename T> void append(T val) 
  18.         { 
  19.             append((easy_uint8*)&val,sizeof(val));
  20.         }

  21.         void append(const easy_uint8* src, size_t cnt)
  22.         {
  23.             if (!cnt)
  24.             {
  25.                 return;
  26.             }

  27.             //    case 1: rpos_ <= wpos_
  28.             if (rpos_ <= wpos_)
  29.             {
  30.                 if (size_ - wpos_ >= cnt)
  31.                 {
  32.                     memmove(buffer_ + wpos_,src,cnt);
  33.                     wpos_ += cnt;
  34.                     return;
  35.                 }
  36.                 else
  37.                 {
  38.                     if (size_ - wpos_ + rpos_ > cnt)    // >= is ok>
  39.                     {
  40.                         memmove(buffer_ + wpos_, src, size_ - wpos_);
  41.                         memmove(buffer_, src + size_ - wpos_, cnt - (size_ - wpos_));
  42.                         wpos_ = cnt - (size_ - wpos_);
  43.                         return;
  44.                     }
  45.                     else
  46.                     {
  47.                         _Type* new_buffer = _allocate(size_ + cnt - (size_ - wpos_));
  48.                         memmove(new_buffer,buffer_,wpos_);
  49.                         memmove(new_buffer + wpos_, src, cnt);
  50.                         _deallocate(buffer_,size_);
  51.                         size_ = size_ + cnt - (size_ - wpos_);
  52.                         wpos_ += cnt;
  53.                         buffer_ = new_buffer;
  54.                         return;
  55.                     }
  56.                 }
  57.             }
  58.             //    case 2: rpos_ > wpos_ 
  59.             else if(rpos_ > wpos_)
  60.             {
  61.                 if (rpos_ - wpos_ > cnt)    // >= is ok ?
  62.                 {
  63.                     if (rpos_ - wpos_ > cnt)
  64.                     {
  65.                         memmove(buffer_ + wpos_,src,cnt);
  66.                         wpos_ += cnt;
  67.                         return;
  68.                     }
  69.                     else
  70.                     {
  71.                         _Type* new_buffer = _allocate(size_ + cnt - (rpos_ - wpos_) + EXTRA_BUFFER_SIZE);
  72.                         memmove(new_buffer,buffer_,wpos_);
  73.                         memmove(new_buffer + wpos_,src,cnt);
  74.                         memmove(new_buffer + wpos_ + cnt - (rpos_ - wpos_) + EXTRA_BUFFER_SIZE,buffer_ + rpos_,size_ - rpos_);
  75.                         _deallocate(buffer_,size_);
  76.                         rpos_ += cnt - (rpos_ - wpos_) + EXTRA_BUFFER_SIZE;
  77.                         wpos_ += cnt;
  78.                         size_ = size_ + cnt - (rpos_ - wpos_) + EXTRA_BUFFER_SIZE;
  79.                         buffer_ = new_buffer;
  80.                         return;
  81.                     }
  82.                 }
  83.             }
  84.         }

  85.         EasyRingbuffer& operator << (easy_bool val)
  86.         {
  87.             append<easy_bool>(val);
  88.             return *this;
  89.         }

  90.         EasyRingbuffer& operator << (easy_uint8 val)
  91.         {
  92.             append<easy_uint8>(val);
  93.             return *this;
  94.         }

  95.         EasyRingbuffer& operator << (easy_uint16 val)
  96.         {
  97.             append<easy_uint16>(val);
  98.             return *this;
  99.         }

  100.         EasyRingbuffer& operator << (easy_uint32 val)
  101.         {
  102.             append<easy_uint32>(val);
  103.             return *this;
  104.         }

  105.         EasyRingbuffer& operator << (easy_uint64 val)
  106.         {
  107.             append<easy_uint64>(val);
  108.             return *this;
  109.         }

  110.         EasyRingbuffer& operator << (easy_int8 val)
  111.         {
  112.             append<easy_int8>(val);
  113.             return *this;
  114.         }

  115.         EasyRingbuffer& operator << (easy_int16 val)
  116.         {
  117.             append<easy_int16>(val);
  118.             return *this;
  119.         }

  120.         EasyRingbuffer& operator << (easy_int32 val)
  121.         {
  122.             append<easy_int32>(val);
  123.             return *this;
  124.         }

  125.         EasyRingbuffer& operator << (easy_int64 val)
  126.         {
  127.             append<easy_int64>(val);
  128.             return *this;
  129.         }

  130.         EasyRingbuffer& operator << (easy_float val)
  131.         {
  132.             append<easy_float>(val);
  133.             return *this;
  134.         }

  135.         EasyRingbuffer& operator << (easy_double val)
  136.         {
  137.             append<easy_double>(val);
  138.             return *this;
  139.         }

  140.         EasyRingbuffer& operator << (const std::string& val)
  141.         {
  142.             append((easy_uint8 const*)val.c_str(),val.length());
  143.             return *this;
  144.         }

  145.         EasyRingbuffer& operator << (const char* val)
  146.         {
  147.             append((easy_uint8 const *)val, val ? strlen(val) : 0);
  148.             return *this;
  149.         }

  150.         template<typename T> T read() 
  151.         {
  152.             T r;
  153.             read((easy_uint8*)&r,sizeof(T));
  154.             return r;
  155.         }

  156.         void read(easy_uint8* des,size_t len)
  157.         {
  158.             if (_read_finish())
  159.             {
  160.                 return;
  161.             }
  162.             if (rpos_ < wpos_)
  163.             {
  164.                 if (wpos_ - rpos_ >= len)
  165.                 {
  166.                     memmove(des,buffer_ + rpos_,len);
  167.                     rpos_ += len;
  168.                 }
  169.                 //    else just skip
  170.             }
  171.             else if (rpos_ > wpos_)
  172.             {
  173.                 if (size_ - rpos_ >= len)
  174.                 {
  175.                     memmove(des,buffer_ + rpos_,len);
  176.                     rpos_ += len;
  177.                 }
  178.                 else
  179.                 {
  180.                     memmove(des,buffer_ + rpos_, size_ - rpos_);
  181.                     memmove(des + size_ - rpos_, buffer_, len - (size_ - rpos_));
  182.                     rpos_ = len - (size_ - rpos_);
  183.                 }
  184.             }
  185.         }

  186.         EasyRingbuffer& operator >> (easy_bool& val)
  187.         {
  188.             val = read<easy_bool>();
  189.             return *this;
  190.         }

  191.         EasyRingbuffer& operator >> (easy_uint8& val)
  192.         {
  193.             val = read<easy_uint8>();
  194.             return *this;
  195.         }

  196.         EasyRingbuffer& operator >> (easy_uint16& val)
  197.         {
  198.             val = read<easy_uint16>();
  199.             return *this;
  200.         }

  201.         EasyRingbuffer& operator >> (easy_uint32& val)
  202.         {
  203.             val = read<easy_uint32>();
  204.             return *this;
  205.         }

  206.         EasyRingbuffer& operator >> (easy_uint64& val)
  207.         {
  208.             val = read<easy_uint64>();
  209.             return *this;
  210.         }

  211.         EasyRingbuffer& operator >> (easy_int8& val)
  212.         {
  213.             val = read<easy_int8>();
  214.             return *this;
  215.         }

  216.         EasyRingbuffer& operator >> (easy_int16& val)
  217.         {
  218.             val = read<easy_int16>();
  219.             return *this;
  220.         }

  221.         EasyRingbuffer& operator >> (easy_int32& val)
  222.         {
  223.             val = read<easy_int32>();
  224.             return *this;
  225.         }

  226.         EasyRingbuffer& operator >> (easy_int64& val)
  227.         {
  228.             val = read<easy_int64>();
  229.             return *this;
  230.         }

  231.         EasyRingbuffer& operator >> (easy_float& val)
  232.         {
  233.             val = read<easy_float>();
  234.             return *this;
  235.         }

  236.         EasyRingbuffer& operator >> (easy_double& val)
  237.         {
  238.             val = read<easy_double>();
  239.             return *this;
  240.         }

  241.         size_t size() const { return size_; }

  242.         size_t rpos() const { return rpos_; }

  243.         size_t wpos() const { return wpos_; }

  244.     private:
  245.         _Type* _allocate(size_t size) 
  246.         { 
  247.             _Type* res = 0;
  248.             res = static_cast<_Type*>(alloc_type_.allocate(size)); 
  249.             return res;
  250.         }

  251.         void _deallocate(void* p,size_t size) 
  252.         { 
  253.             alloc_type_.deallocate(p,size); 
  254.         }

  255.         void _reallocate(void* p,size_t old_size,size_t new_size) { alloc_type_.reallocate(p,old_size,new_size); }

  256.         easy_bool _read_finish() { return wpos_ == rpos_; }

  257.     private:
  258.         EasyRingbuffer ( const EasyRingbuffer& );
  259.         EasyRingbuffer& operator = ( const EasyRingbuffer& );
  260.     private:
  261.         size_t            size_;

  262.         _Type*            buffer_;

  263.         size_t            wpos_;

  264.         size_t            rpos_;

  265.         allocator_type    alloc_type_;
  266.     };
  267. }
 
  二 空闲列表

    空闲列表的原理比较简单,一般用于比较大的对象,可预分配一定数量的对象,需要时直接空闲列表中取,使用完后收回,如果空闲列表中已空,则需要重新设置大小了;也可使用时分配,使用完后收回。实现代码如下:

点击(此处)折叠或打开

  1. // use stl
  2.     template<typename _Type, typename _Lock,typename _StorageType /*= std::list<_Type*>*/>
  3.     class lock_queue     
  4.     {
  5.         typedef typename _Type::_Key                _Key;

  6.         static const size_t MAX_POOL_SIZE = _Type::MAX_POOL_SIZE;

  7.     public:
  8.         _Type* allocate(_Key __key)
  9.         {
  10.             _Type* __ret = 0;
  11.             if (free_list_.empty())
  12.             {
  13.                 __ret = new _Type(__key);
  14.             }
  15.             else
  16.             {
  17.                 lock_.acquire_lock();
  18.                 __ret = free_list_.back();
  19.                 free_list_.pop_back();
  20.                 lock_.release_lock();
  21.             }
  22.             return __ret;
  23.         }

  24.         void deallcate(_Type* __val)
  25.         {
  26.             if (!__val)
  27.             {
  28.                 return;
  29.             }
  30.             if (MAX_POOL_SIZE < free_list_.size())
  31.             {
  32.                 delete __val;
  33.                 return;
  34.             }
  35.             lock_.acquire_lock();
  36.             free_list_.push_back(__val);
  37.             lock_.release_lock();
  38.         }

  39.         size_t free_size() /*const*/ 
  40.         { 
  41.             size_t __size = 0;
  42.             lock_.acquire_lock(); 
  43.             __size = free_list_.size(); 
  44.             lock_.release_lock();
  45.             return __size;
  46.         }

  47.         void clear() 
  48.         { 
  49.             lock_.acquire_lock(); 
  50.             for (typename _StorageType::iterator __it = free_list_.begin(); __it != free_list_.end(); ++__it)
  51.             {
  52.                 if ((*__it))
  53.                 {
  54.                     delete (*__it);
  55.                     (*__it) = NULL;
  56.                 }
  57.             }
  58.             free_list_.clear(); 
  59.             _StorageType().swap(free_list_); 
  60.             lock_.release_lock();
  61.         }

  62.         ~lock_queue()
  63.         {
  64.             clear();
  65.         }
  66.     private:
  67.         _Lock                        lock_;
  68.         _StorageType                free_list_;
  69.     };

点击(此处)折叠或打开

  1. //anther way,use use stl
  2. template < typename T, int DEFAULT_BLOCK_NUM = 1024 >
  3. class CMemoryPool 
  4. {
  5. public:
  6.     static VOID* operator new ( std::size_t nAllocLength )
  7.     {
  8.         Assert( sizeof(T) == nAllocLength ); 
  9.         Assert( sizeof(T) >= sizeof(UCHAR*) );
  10.         if ( !m_sNewPointer )
  11.         {
  12.             allocBlock();
  13.         }
  14.         UCHAR* ucReturnPointer = m_sNewPointer;
  15.         //the head of 4 bytes is explain the next pointer of memory force,
  16.         //and m_NewPointer just point the next block of memory,when used the next allocation
  17.         m_sNewPointer = *reinterpret_cast<UCHAR**>( ucReturnPointer);
  18.         return ucReturnPointer;
  19.     }

  20.     static VOID operator delete( void* vpDeletePointer )
  21.     {
  22.         *reinterpret_cast<UCHAR**>( vpDeletePointer) = m_sNewPointer;    
  23.         m_sNewPointer = static_cast<UCHAR*>(vpDeletePointer);
  24.     }

  25.     static VOID allocBlock()
  26.     {
  27.         m_sNewPointer = new UCHAR[sizeof(T) * DEFAULT_BLOCK_NUM]; 
  28.         //casting dual pointer force,that will change the meaning of the head of 4 byte memory 
  29.         UCHAR **ppCurent = reinterpret_cast<UCHAR**>( m_sNewPointer ); 
  30.         UCHAR *ppNext = m_sNewPointer; 
  31.         for( int i = 0; i < DEFAULT_BLOCK_NUM-1; i++ ) 
  32.         {
  33.             ppNext += sizeof(T); 
  34.             *ppCurent = ppNext; 
  35.             //the head of 4 bytes is explain the next pointer of memory force,a memory list in form. 
  36.             ppCurent = reinterpret_cast<UCHAR**>( ppNext ); 
  37.         }
  38.         //if the last memory bock, the head of 4 byte is null
  39.         *ppCurent = 0; 
  40.     }

  41. protected:
  42.     virtual ~CMemoryPool()
  43.     {

  44.     }
  45. private:
  46.     static UCHAR *m_sNewPointer; 
  47. };

  48. template<class T, int BLOCK_NUM > 
  49. UCHAR *CMemoryPool<T, BLOCK_NUM >::m_sNewPointer;

    三  stl的二级分配器

    stl内部实现的分配器分两种情况:一种是大于128byte的分配,直接使用系统的内存分配函数malloc/free;另外一种为小于128byte的,也就是上面说的二级分配器,它采用了某些技术来管来内存,避免频繁分配释放。简单的说,就是将内存按8字节对齐,分别建立固定值倍数大小的内存池,如8, 8*2 ,8*3..., 当需要分配内存时,根据分配内存的大小,算出所需内存大小的内存池索引,然后根据这个索引找到那块内存池,并从中取出一块返回;同样,内存使用完后,按类似的方法回收。这种方案一般适用于比较小的内存分配的情况,大的可以考虑其他的方案。其流程如下:


下面是具体代码:

点击(此处)折叠或打开

  1. template< bool threads, int inst >
  2.     class __default_alloc_template
  3.     {
  4.         enum {_ALIGN = 8};
  5.         enum {_MAX_BYTES = 128};
  6.         enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
  7.     
  8.         static size_t _S_round_up(size_t __bytes) { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }

  9.         static size_t _S_freelist_index(size_t __bytes) { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); }

  10.         union _Obj 
  11.         {
  12.             union _Obj* _M_free_list_link;
  13.             char _M_client_data[1]; /* The client sees this. */
  14.         };
  15.         static _Obj* volatile _S_free_list[_NFREELISTS]; 

  16.         // Returns an object of size __n, and optionally adds to size __n free list.
  17.         static void* _S_refill(size_t __n);

  18.         // Allocates a chunk for nobjs of size size. nobjs may be reduced
  19.         // if it is inconvenient to allocate the requested number.
  20.         static char* _S_chunk_alloc(size_t __size, int& __nobjs);

  21.         static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);

  22.         // Chunk allocation state.
  23.         static char*    _S_start_free;
  24.         static char*    _S_end_free;
  25.         static size_t    _S_heap_size;

  26.     public:
  27.         static void* allocate(size_t __n)
  28.         {
  29.             void* __ret = 0;
  30.             if (__n > (size_t) _MAX_BYTES) 
  31.             {
  32.                 __ret = malloc_alloc::allocate(__n);
  33.             }
  34.             else
  35.             {
  36.                 mutex_lock    __lock;
  37.                 __lock.acquire_lock();
  38.                 _Obj* volatile* __my_free_list = _S_free_list + _S_freelist_index(__n);
  39.                 _Obj* volatile __result = *__my_free_list;
  40.                 if (__result == 0)
  41.                 {
  42.                     __ret = _S_refill(_S_round_up(__n));
  43.                 }
  44.                 else 
  45.                 {
  46.                     *__my_free_list = __result -> _M_free_list_link;
  47.                     __ret = __result;
  48.                 }
  49.                 __lock.release_lock();
  50.             }
  51.             return __ret;
  52.         }

  53.         /* __p may not be 0 */
  54.         static void deallocate(void* __p, size_t __n)
  55.         {
  56.             if (__n > (size_t) _MAX_BYTES)
  57.             {
  58.                  malloc_alloc::deallocate(__p, __n);
  59.             }
  60.             else 
  61.             {
  62.                 mutex_lock    __lock;
  63.                 __lock.acquire_lock();
  64.                  _Obj* volatile* __my_free_list = _S_free_list + _S_freelist_index(__n);
  65.                  _Obj* __q = (_Obj*)__p;
  66.                  __q -> _M_free_list_link = *__my_free_list;
  67.                  *__my_free_list = __q;
  68.                  __lock.release_lock();
  69.             }
  70.         }
  71.     };

  72.     template <bool __threads, int __inst>
  73.     inline bool operator==(const __default_alloc_template<__threads, __inst>&,
  74.         const __default_alloc_template<__threads, __inst>&)
  75.     {
  76.         return true;
  77.     }

  78.     template <bool __threads, int __inst>
  79.     inline bool operator!=(const __default_alloc_template<__threads, __inst>&,
  80.         const __default_alloc_template<__threads, __inst>&)
  81.     {
  82.         return false;
  83.     }

  84.     /* We allocate memory in large chunks in order to avoid fragmenting */
  85.     /* the malloc heap too much. */
  86.     /* We assume that size is properly aligned. */
  87.     /* We hold the allocation lock. */
  88.     template <bool __threads, int __inst>
  89.     char*    __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, int& __nobjs)
  90.     {
  91.         //::_set_new_handler(_out_of_memory);
  92.         char* __result;
  93.         size_t __total_bytes = __size * __nobjs;
  94.         size_t __bytes_left = _S_end_free - _S_start_free;
  95.         //    enough memory to alloc
  96.         if (__bytes_left >= __total_bytes) 
  97.         {
  98.             __result = _S_start_free;
  99.             _S_start_free += __total_bytes;
  100.             return(__result);
  101.         } 
  102.         //    only more than __size can be alloc
  103.         else if (__bytes_left >= __size) 
  104.         {
  105.             __nobjs = (int)(__bytes_left/__size);
  106.             __total_bytes = __size * __nobjs;
  107.             __result = _S_start_free;
  108.             _S_start_free += __total_bytes;
  109.             return(__result);
  110.         } 
  111.         else 
  112.         {
  113.             size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
  114.             // Try to make use of the left-over piece.
  115.             if (__bytes_left > 0) 
  116.             {
  117.                 _Obj* volatile* __my_free_list = _S_free_list + _S_freelist_index(__bytes_left);
  118.                 ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
  119.                 *__my_free_list = (_Obj*)_S_start_free;
  120.             }
  121.             //    alloc __bytes_to_get again
  122.             _S_start_free = (char*)malloc(__bytes_to_get);

  123.             //    alloc failed
  124.             if (== _S_start_free) 
  125.             {
  126.                 size_t __i;
  127.                 _Obj* volatile* __my_free_list;
  128.                 _Obj* __p;
  129.                 // Try to make do with what we have. That can't
  130.                 // hurt. We do not try smaller requests, since that tends
  131.                 // to result in disaster on multi-process machines.
  132.                 for (__i = __size; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN) 
  133.                 {
  134.                     __my_free_list = _S_free_list + _S_freelist_index(__i);
  135.                     __p = *__my_free_list;
  136.                     if (!= __p) 
  137.                     {
  138.                         *__my_free_list = __p -> _M_free_list_link;
  139.                         _S_start_free = (char*)__p;
  140.                         _S_end_free = _S_start_free + __i;
  141.                         return(_S_chunk_alloc(__size, __nobjs));
  142.                         // Any leftover piece will eventually make it to the
  143.                         // right free list.
  144.                     }
  145.                 }
  146.                 _S_end_free = 0;    // In case of exception.
  147.                 _S_start_free = (char*) malloc(__bytes_to_get);
  148.                 // This should either throw an
  149.                 // exception or remedy the situation. Thus we assume it
  150.                 // succeeded.
  151.             }
  152.             _S_heap_size += __bytes_to_get;
  153.             _S_end_free = _S_start_free + __bytes_to_get;
  154.             return(_S_chunk_alloc(__size, __nobjs));
  155.         }
  156.     }

  157.     /* Returns an object of size __n, and optionally adds to size __n free list.*/
  158.     /* We assume that __n is properly aligned. */
  159.     /* We hold the allocation lock. */
  160.     template <bool __threads, int __inst>
  161.     void* __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
  162.     {
  163.         int __nobjs = 20;
  164.         char* __chunk = _S_chunk_alloc(__n, __nobjs);
  165.         _Obj* volatile* __my_free_list;
  166.         _Obj* __result;
  167.         _Obj* __current_obj;
  168.         _Obj* __next_obj;
  169.         int __i;

  170.         if (== __nobjs) 
  171.         {
  172.             return(__chunk);
  173.         }
  174.         __my_free_list = _S_free_list + _S_freelist_index(__n);

  175.         /* Build free list in chunk */
  176.         __result = (_Obj*)__chunk;
  177.         *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
  178.         for (__i = 1; ; __i++) 
  179.         {
  180.             __current_obj = __next_obj;
  181.             __next_obj = (_Obj*)((char*)__next_obj + __n);
  182.             if (__nobjs - 1 == __i) 
  183.             {
  184.                 __current_obj -> _M_free_list_link = 0;
  185.                 break;
  186.             } 
  187.             else 
  188.             {
  189.                 __current_obj -> _M_free_list_link = __next_obj;
  190.             }
  191.         }
  192.         return(__result);
  193.     }

  194.     template <bool threads, int inst>
  195.     void* __default_alloc_template<threads, inst>::reallocate(void* __p, size_t __old_sz, size_t __new_sz)
  196.     {
  197.         mutex_lock    __lock;
  198.         __lock.acquire_lock();
  199.         void* __result;
  200.         size_t __copy_sz;

  201.         if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) 
  202.         {
  203.             __lock.release_lock();
  204.             return(realloc(__p, __new_sz));
  205.         }
  206.         if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) 
  207.         {
  208.             __lock.release_lock();
  209.             return(__p);
  210.         }
  211.         __result = allocate(__new_sz);
  212.         __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
  213.         memcpy(__result, __p, __copy_sz);
  214.         deallocate(__p, __old_sz);
  215.         __lock.release_lock();
  216.         return(__result);
  217.     }

  218.     template< bool threads, int inst >
  219.     char* __default_alloc_template<threads, inst>::_S_start_free = 0;

  220.     template< bool threads, int inst >
  221.     char* __default_alloc_template<threads, inst>::_S_end_free = 0;

  222.     template< bool threads, int inst >
  223.     size_t __default_alloc_template<threads, inst>::_S_heap_size = 0;

  224.     template <bool __threads, int __inst>
  225.     typename __default_alloc_template<__threads, __inst>::_Obj* volatile
  226.         __default_alloc_template<__threads, __inst> ::_S_free_list[_NFREELISTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };

 参考:
    sqi stl
      http://www.sgi.com/tech/stl/
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页