boost.pool源码整理和使用说明

Source

#ifndef __KIMI_BOOST_POOL

#define __KIMI_BOOST_POOL

#pragma once

 

 

// std::less, std::less_equal, std::greater

#include <functional>

// new[], delete[], std::nothrow

#include <new>

// std::size_t, std::ptrdiff_t

#include <cstddef>

// std::malloc, std::free

#include <cstdlib>

// std::invalid_argument

#include <exception>

// std::max

#include <algorithm>

 

#include <boost/pool/detail/ct_gcd_lcm.hpp>

#include <boost/pool/detail/gcd_lcm.hpp>

#include <boost/static_assert.hpp>

 

 

namespace kimi_boost

{

 

///声明/

//底层分配策略的两个策略类(policy classes)

struct default_user_allocator_new_delete;

struct default_user_allocator_malloc_free;

 

//管理Block的类(每个Block分为多个Chunk)

template <typename SizeType = std::size_t>

class simple_segregated_storage;

 

//内存池(继承自'class simple_segregated_storage')

template <typename UserAllocator = default_user_allocator_new_delete>

class pool;

 

//对象池(继承自'内存池'),增加了对象的自动构造,析构

template <typename T, typename UserAllocator = default_user_allocator_new_delete>

class object_pool;

 

namespace details

{

//POD代表向系统索要的一大块Block,再加上必要的管理

//PODptr管理一个个Block,形成一个free list

template <typename SizeType>

class PODptr;

};

}//namespace kimi_boost

 

///实现/

namespace kimi_boost

{

//new/delete的分配策略

struct default_user_allocator_new_delete

{

  typedef std::size_t size_type;

  typedef std::ptrdiff_t difference_type;

 

  static char * malloc(const size_type bytes)

  { return new (std::nothrow) char[bytes]; }

  static void free(char * const block)

  { delete [] block; }

};

//malloc/free的分配策略

struct default_user_allocator_malloc_free

{

  typedef std::size_t size_type;

  typedef std::ptrdiff_t difference_type;

 

  static char * malloc(const size_type bytes)

  { return reinterpret_cast<char *>(std::malloc(bytes)); }

  static void free(char * const block)

  { std::free(block); }

};

 

 

namespace details

{

 

template <typename SizeType>

class PODptr

{

public:

       typedef SizeType size_type;

 

private:

    char * ptr;//指向的Block

    size_type sz;//指向的所有Block的字节数

 

    char * ptr_next_size() const

    { return (ptr + sz - sizeof(size_type)); }

 

    char * ptr_next_ptr() const

    {

      return (ptr_next_size() -

          ::boost::details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);

    }

 

public:

    PODptr(char * const nptr, const size_type nsize)

    :ptr(nptr), sz(nsize) { }

    PODptr()

    :ptr(0), sz(0) { }

 

    bool valid() const { return (begin() != 0); }

    void invalidate() { begin() = 0; }

    char * & begin() { return ptr; }

    char * begin() const { return ptr; }

    char * end() const { return ptr_next_ptr(); }

    size_type total_size() const { return sz; }

    size_type element_size() const

    {

      return (sz - sizeof(size_type) -

                ::boost::details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);

    }

 

    size_type & next_size() const

    { return *(reinterpret_cast<size_type *>(ptr_next_size())); }

    char * & next_ptr() const

    { return *(reinterpret_cast<char **>(ptr_next_ptr())); }

 

    PODptr next() const

    { return PODptr<size_type>(next_ptr(), next_size()); }

    void next(const PODptr & arg) const

    {

      next_ptr() = arg.begin();

      next_size() = arg.total_size();

    }

};

} // namespace details

 

 

 

 

 

 

 

 

 

template <typename SizeType>

class simple_segregated_storage

{

public:

    typedef SizeType size_type;

 

private:

         //不允许拷贝构造和赋值

    simple_segregated_storage(const simple_segregated_storage &);

    void operator=(const simple_segregated_storage &);

 

    static void * try_malloc_n(void * & start, size_type n,

        size_type partition_size);

 

protected:

    void * first;

    void * find_prev(void * ptr);

       //得到ptr所指向的地址

    static void * & nextof(void * const ptr)

    { return *(static_cast<void **>(ptr)); }

 

public:

    simple_segregated_storage()

    :first(0) { }

    static void * segregate(void * block,

        size_type nsz, size_type npartition_sz,

        void * end = 0);

 

       //nsznpartition_sz的倍数,nszchunk的总字节数,npartition_szchunk的数量

       //block细切,然后把该block加入到free list中的最前面去

    void add_block(void * const block,

        const size_type nsz, const size_type npartition_sz)

    {

      first = segregate(block, nsz, npartition_sz, first);

    }

 

       //nsznpartition_sz的倍数

       //block细切,然后把该block加入到free list中合适的位置上

    void add_ordered_block(void * const block, const size_type nsz, const size_type npartition_sz)

    {

      //找到block应该加入的地方

      void * const loc = find_prev(block);

 

      if (loc == 0)//加入到free list中的最前面

        add_block(block, nsz, npartition_sz);

      else//挂链,加入到free list的中间

        nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));

    }

 

    bool empty() const { return (first == 0); }

 

       //直接将free list最前面的空闲内存分配

    void * malloc()

       {

              void * const ret = first;

              //调整free list的头指针

              first = nextof(first);

              return ret;

       }

 

    //chunk必须是malloc()函数返回

    //chunk收回,放到free list的头部

    void free(void * const chunk)

    {

              //chunk加入free list的头部

              nextof(chunk) = first;

              first = chunk;

    }

 

       //chunk必须是malloc()函数返回

       //chunk收回,放到free list中合适的位置

    void ordered_free(void * const chunk)

    {

      //找到chunk应该加入的地方

      void * const loc = find_prev(chunk);

      //chunk加入free list中合适的位置

      if (loc == 0)//头部

        free(chunk);

      else

      {//挂链,加入到free list的中间

        nextof(chunk) = nextof(loc);

        nextof(loc) = chunk;

      }

    }

 

    // Note: if you're allocating/deallocating n a lot, you should

    //  be using an ordered pool.

    void * malloc_n(size_type n, size_type partition_size);

 

       //chunks是本对象分配的malloc_n函数分配的空间

       //并且npartition_size两个参数也要一致

       //释放chunks的内存

    void free_n(void * const chunks, const size_type n,

        const size_type partition_size)

    {

      add_block(chunks, n * partition_size, partition_size);

    }

 

       //同上函数

    void ordered_free_n(void * const chunks, const size_type n,

        const size_type partition_size)

    {

      add_ordered_block(chunks, n * partition_size, partition_size);

    }

};

 

 

//函数:simple_segregated_storage::find_prev

 

//遍历free list,返回如果ptr加入到free list,ptr的前一个chunk的位置(按照地址的高低排序)

//返回,表明ptr应该在free list头部

template <typename SizeType>

void * simple_segregated_storage<SizeType>::find_prev(void * const ptr)

{

  //如果free list为空,或者first > ptr,返回(表明ptr应该加在free list头部)

  if (first == 0 || std::greater<void *>()(first, ptr))

    return 0;

 

  void * iter = first;

  while (true)

  {

    if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr))

      return iter;

 

    iter = nextof(iter);

  }

}

 

 

//函数:simple_segregated_storage::segregate

 

//要求:

//1. npartition_sz >= sizeof(void *)

//2. nsz >= npartition_sz

//3. npartition_sz = sizeof(void *) * i

 

//将一块block细切(block开头,下一个block的开头是end),然后将其挂到end的前面

//blocksz个字节,每个chunkpartition_sz字节

template <typename SizeType>

void * simple_segregated_storage<SizeType>::segregate(

    void * const block,

    const size_type sz,

    const size_type partition_sz,

    void * const end)

{

       //计算出block中最后一个有效的chunk的指针

       //old == block + partition_sz * i

       char * old = static_cast<char *>(block)

              + ((sz - partition_sz) / partition_sz) * partition_sz;

 

       //令它指向下一个block的开头

       nextof(old) = end;

 

       //如果该block只有一个chunk的空间(sz == partition_sz)

       if (old == block) return block;

 

       //从后往前,将这个block中的每个chunk挂链,形成一个单向链表

       for (char * iter = old - partition_sz ; iter != block ; old = iter, iter -= partition_sz)

              nextof(iter) = old;

       nextof(block) = old;

 

       return block;

}

 

 

 

//函数:simple_segregated_storage::try_malloc_n

 

//要求:

//1. n > 0

//2. start != 0

//3. nextof(start) != 0

 

//尝试在free list,start(start不包括)开始,找到n个临近的大小为partition_sizechunk,

//成功返回最后一个chunk的指针.这样,空闲的内存区域为[start,返回值](但是不能使用,因为没有分配)

//失败返回,不分配任何内存.start会被改变为最后一个尝试的chunk块的指针

 

template <typename SizeType>

void * simple_segregated_storage<SizeType>::try_malloc_n(

    void * & start, size_type n, const size_type partition_size)

{

  void * iter = nextof(start);

  while (--n != 0)

  {

    void * next = nextof(iter);

    if (next != static_cast<char *>(iter) + partition_size)

    {

      //next, 或者不连续

      start = iter;

      return 0;

    }

       //iter前进,继续判断

    iter = next;

  }

  return iter;

}

 

//函数:simple_segregated_storage::malloc_n

 

//尝试在free list,start(start不包括)开始,找到n个临近的大小为partition_sizechunk,

//成功返回最后一个chunk的指针.这样,空闲的内存区域为[start,返回值](但是不能使用,因为没有分配)

 

//失败返回,不分配任何内存.

 

template <typename SizeType>

void * simple_segregated_storage<SizeType>::malloc_n(const size_type n,

    const size_type partition_size)

{

       void * start = &first;

       void * iter;

       do

       {

              if (nextof(start) == 0)

                     return 0;

              //注意:并不是死循环,starttry_malloc_n返回时会被改变

              iter = try_malloc_n(start, n, partition_size);

       } while (iter == 0);

 

       void * const ret = nextof(start);

       nextof(start) = nextof(iter);

       return ret;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

template <typename UserAllocator>

class pool: protected simple_segregated_storage<

    typename UserAllocator::size_type>

{

  public:

    typedef UserAllocator user_allocator;

    typedef typename UserAllocator::size_type size_type;

    typedef typename UserAllocator::difference_type difference_type;

 

  private:

    BOOST_STATIC_CONSTANT(unsigned, min_alloc_size =

        (::boost::details::pool::ct_lcm<sizeof(void *), sizeof(size_type)>::value) );

 

    // Returns 0 if out-of-memory

    // Called if malloc/ordered_malloc needs to resize the free list

    void * malloc_need_resize();

    void * ordered_malloc_need_resize();

 

  protected:

    details::PODptr<size_type> list;

    const size_type requested_size;

    size_type next_size;

 

 

    simple_segregated_storage<size_type> & store() { return *this; }//向上转型

    const simple_segregated_storage<size_type> & store() const { return *this; }//向上转型

    details::PODptr<size_type> find_POD(void * const chunk) const;//查找chunk是哪个POD分配的

 

    //判断chunk是否在block i,其中block i中有sizeof_ichunk

    static bool is_from(void * const chunk, char * const i,

        const size_type sizeof_i)

    {

              //i <= chunk < i+sizeof_i

              std::less_equal<void *> lt_eq;

              std::less<void *> lt;

              return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i));

    }

 

    size_type alloc_size() const

    {

              const unsigned min_size = min_alloc_size;

              return ::boost::details::pool::lcm<size_type>(requested_size, min_size);

    }

 

 

    static void * & nextof(void * const ptr)

    { return *(static_cast<void **>(ptr)); }

 

  public:

    // The second parameter here is an extension!

    // pre: npartition_size != 0 && nnext_size != 0

    explicit pool(const size_type nrequested_size,

        const size_type nnext_size = 32)

    :list(0, 0), requested_size(nrequested_size), next_size(nnext_size)

    { }

 

    ~pool() { purge_memory(); }

    bool release_memory();//释放未被分配的block,返回true成功

    bool purge_memory();//释放所有block,返回true成功

 

    // These functions are extensions!

    size_type get_next_size() const { return next_size; }

    void set_next_size(const size_type nnext_size) { next_size = nnext_size; }

 

 

       //所有的分配函数失败时返回

 

       void * malloc()

    {

      // Look for a non-empty storage

              if (!store().empty())

                     return store().malloc();

              return malloc_need_resize();

    }

 

    void * ordered_malloc()

    {

      // Look for a non-empty storage

              if (!store().empty())

                     return store().malloc();

              return ordered_malloc_need_resize();

    }

 

  

    void * ordered_malloc(size_type n);//分配连续的nchunk

 

    //chunk必须是*this.malloc()分配的

    void free(void * const chunk){ store().free(chunk); }

       //同上

    void ordered_free(void * const chunk){ store().ordered_free(chunk); }

       //同上

    void free(void * const chunks, const size_type n)

    {

      const size_type partition_size = alloc_size();//chunk的大小

      const size_type total_req_size = n * requested_size;//总字节数量

      const size_type num_chunks = total_req_size / partition_size +//chunk的数量

          ((total_req_size % partition_size) ? true : false);//为什么不写或者???

 

      store().free_n(chunks, num_chunks, partition_size);

    }

    //同上

    void ordered_free(void * const chunks, const size_type n)

    {

      const size_type partition_size = alloc_size();

      const size_type total_req_size = n * requested_size;

      const size_type num_chunks = total_req_size / partition_size +

          ((total_req_size % partition_size) ? true : false);

 

      store().ordered_free_n(chunks, num_chunks, partition_size);

    }

 

    //判断chunk是否是本对象分配的

    bool is_from(void * const chunk) const

    {

      return (find_POD(chunk).valid());

    }

};

 

 

 

 

 

template <typename UserAllocator>

bool pool<UserAllocator>::release_memory()

{

  bool ret = false;

 

       //block队列上当前和过去的iterator pair

       details::PODptr<size_type> ptr = list;

       details::PODptr<size_type> prev;

 

       //chunk队列上当前和过去的iterator pair

       //注意:prev_free指向的是chunk队列上当前block之前的空闲chunk

       void * free = this->first;

       void * prev_free = 0;

 

       const size_type partition_size = alloc_size();//每个chunk的大小

 

       //遍历搜索所有的已分配的block

       while (ptr.valid())

       {

              if (free == 0)       return ret;

    // At this point:

    //  ptr points to a valid memory block

    //  free points to either:

    //    0 if there are no more free chunks

    //    the first free chunk in this or some next memory block

    //  prev_free points to either:

    //    the last free chunk in some previous memory block

    //    0 if there is no such free chunk

    //  prev is either:

    //    the PODptr whose next() is ptr

    //    !valid() if there is no such PODptr

 

    // If there are no more free memory chunks, then every remaining

    //  block is allocated out to its fullest capacity, and we can't

    //  release any more memory

             

 

    // We have to check all the chunks.  If they are *all* free (i.e., present

    //  in the free list), then we can free the block.

              bool all_chunks_free = true;

 

    // Iterate 'i' through all chunks in the memory block

    // if free starts in the memory block, be careful to keep it there

              void * saved_free = free;

              for (char * i = ptr.begin(); i != ptr.end(); i += partition_size)

              {

      // If this chunk is not free

                     if (i != free)

                     {

        // We won't be able to free this block

                     all_chunks_free = false;

 

        // free might have travelled outside ptr

        free = saved_free;

        // Abort searching the chunks; we won't be able to free this

        //  block because a chunk is not free.

        break;

      }

 

      // We do not increment prev_free because we are in the same block

      free = nextof(free);

    }

 

    // post: if the memory block has any chunks, free points to one of them

    // otherwise, our assertions above are still valid

 

    const details::PODptr<size_type> next = ptr.next();

 

    if (!all_chunks_free)

    {

      if (is_from(free, ptr.begin(), ptr.element_size()))

      {

        std::less<void *> lt;

        void * const end = ptr.end();

        do

        {

          prev_free = free;

          free = nextof(free);

        } while (free && lt(free, end));

      }

      // This invariant is now restored:

      //     free points to the first free chunk in some next memory block, or

      //       0 if there is no such chunk.

      //     prev_free points to the last free chunk in this memory block.

     

      // We are just about to advance ptr.  Maintain the invariant:

      // prev is the PODptr whose next() is ptr, or !valid()

      // if there is no such PODptr

      prev = ptr;

    }

    else

    {

      // All chunks from this block are free

 

      // Remove block from list

      if (prev.valid())

        prev.next(next);

      else

        list = next;

 

      // Remove all entries in the free list from this block

      if (prev_free != 0)

        nextof(prev_free) = free;

      else

        this->first = free;

 

      // And release memory

      UserAllocator::free(ptr.begin());

      ret = true;

    }

 

    // Increment ptr

    ptr = next;

  }

 

  return ret;

}

 

//释放所有已分配的和未分配的内存

template <typename UserAllocator>

bool pool<UserAllocator>::purge_memory()

{

  details::PODptr<size_type> iter = list;

 

  if (!iter.valid())

    return false;

  do

  {

    // hold "next" pointer

    const details::PODptr<size_type> next = iter.next();

    // delete the storage

    UserAllocator::free(iter.begin());

    // increment iter

    iter = next;

  } while (iter.valid());

 

  list.invalidate();

  this->first = 0;

 

  return true;

}

 

 

template <typename UserAllocator>

void * pool<UserAllocator>::malloc_need_resize()

{

       //分配新的区域做block

       const size_type partition_size = alloc_size();//chunk的大小

       const size_type POD_size = next_size * partition_size +//

              ::boost::details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);

 

       //分配空间

       char * const ptr = UserAllocator::malloc(POD_size);

       if (ptr == 0)  return 0;

 

       const details::PODptr<size_type> node(ptr, POD_size);

       next_size <<= 1;//左移位

       //初始化新的空间

       store().add_block(node.begin(), node.element_size(), partition_size);

       //挂链

       node.next(list);

       list = node;

 

       //此时有剩余空间,直接调用分配函数

       return store().malloc();

}

 

template <typename UserAllocator>

void * pool<UserAllocator>::ordered_malloc_need_resize()

{

 

       //分配新的区域做block

       const size_type partition_size = alloc_size();//chunk的大小

       const size_type POD_size = next_size * partition_size +

              ::boost::details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);

 

       //分配空间

       char * const ptr = UserAllocator::malloc(POD_size);

       if (ptr == 0)  return 0;

       const details::PODptr<size_type> node(ptr, POD_size);

       next_size <<= 1;//左移位

 

       //初始化新的空间

       store().add_block(node.begin(), node.element_size(), partition_size);

 

       //找到合适的地方挂链

       if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))

       {

              node.next(list);

              list = node;

       }

       else

       {

              details::PODptr<size_type> prev = list;

 

              while (true)

              {

                     if (prev.next_ptr() == 0 || std::greater<void *>()(prev.next_ptr(), node.begin()))

                            break;

                     prev = prev.next();

              }

              node.next(prev.next());

              prev.next(node);

       }

       //此时有剩余空间,直接调用分配函数

       return store().malloc();

}

 

template <typename UserAllocator>

void * pool<UserAllocator>::ordered_malloc(const size_type n)

{

       const size_type partition_size = alloc_size();

       const size_type total_req_size = n * requested_size;

       const size_type num_chunks = total_req_size / partition_size +

              ((total_req_size % partition_size) ? true : false);

 

       void * ret = store().malloc_n(num_chunks, partition_size);

       if (ret)    return ret;

 

       //没剩余空间,分配

       using std::max;

       next_size = max <size_type>(next_size, num_chunks);

       const size_type POD_size = next_size * partition_size +

              boost::details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);

       //分配

       char * const ptr = UserAllocator::malloc(POD_size);

       if (ptr == 0)  return 0;

       const details::PODptr<size_type> node(ptr, POD_size);

 

  // Split up block so we can use what wasn't requested

  //  (we can use "add_block" here because we know that

  //  the free list is empty, so we don't have to use

  //  the slower ordered version)

  if (next_size > num_chunks)

    store().add_block(node.begin() + num_chunks * partition_size,

        node.element_size() - num_chunks * partition_size, partition_size);

 

  next_size <<= 1;

 

       //找到合适的地方挂链

  if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))

  {

    node.next(list);

    list = node;

  }

  else

  {

    details::PODptr<size_type> prev = list;

 

    while (true)

    {

      // if we're about to hit the end or

      //  if we've found where "node" goes

      if (prev.next_ptr() == 0

          || std::greater<void *>()(prev.next_ptr(), node.begin()))

        break;

 

      prev = prev.next();

    }

 

    node.next(prev.next());

    prev.next(node);

  }

 

  //  and return it.

  return node.begin();

}

 

template <typename UserAllocator>

details::PODptr<typename pool<UserAllocator>::size_type>

pool<UserAllocator>::find_POD(void * const chunk) const

{

       // We have to find which storage this chunk is from.

       details::PODptr<size_type> iter = list;

       while (iter.valid())

       {

              if (is_from(chunk, iter.begin(), iter.element_size()))

                     return iter;

              iter = iter.next();

       }

       return iter;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

template <typename T, typename UserAllocator>

class object_pool: protected pool<UserAllocator>

{

  public:

    typedef T element_type;

    typedef UserAllocator user_allocator;

    typedef typename pool<UserAllocator>::size_type size_type;

    typedef typename pool<UserAllocator>::difference_type difference_type;

 

  protected:

    pool<UserAllocator> & store() { return *this; }

    const pool<UserAllocator> & store() const { return *this; }

 

    // for the sake of code readability :)

    static void * & nextof(void * const ptr)

    { return *(static_cast<void **>(ptr)); }

 

  public:

    // This constructor parameter is an extension!

    explicit object_pool(const size_type next_size = 32)

    :pool<UserAllocator>(sizeof(T), next_size) { }

 

    ~object_pool();

 

    // Returns 0 if out-of-memory

    element_type * malloc()

    { return static_cast<element_type *>(store().ordered_malloc()); }

    void free(element_type * const chunk)

    { store().ordered_free(chunk); }

    bool is_from(element_type * const chunk) const

    { return store().is_from(chunk); }

 

    element_type * construct()

    {

      element_type * const ret = malloc();

      if (ret == 0)

        return ret;

      try { new (ret) element_type(); }//placement new

      catch (...) { free(ret); throw; }

      return ret;

    }

 

    // Include automatically-generated file for family of template construct()

    //  functions

#ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS

#   include <boost/pool/detail/pool_construct.inc>

#else

#   include <boost/pool/detail/pool_construct_simple.inc>

#endif

 

    void destroy(element_type * const chunk)

    {

      chunk->~T();

      free(chunk);

    }

 

    // These functions are extensions!

    size_type get_next_size() const { return store().get_next_size(); }

    void set_next_size(const size_type x) { store().set_next_size(x); }

};

 

template <typename T, typename UserAllocator>

object_pool<T, UserAllocator>::~object_pool()

{

  // handle trivial case

  if (!this->list.valid())

    return;

 

  details::PODptr<size_type> iter = this->list;

  details::PODptr<size_type> next = iter;

 

  // Start 'freed_iter' at beginning of free list

  void * freed_iter = this->first;

 

  const size_type partition_size = this->alloc_size();

 

  do

  {

    // increment next

    next = next.next();

 

    // delete all contained objects that aren't freed

 

    // Iterate 'i' through all chunks in the memory block

    for (char * i = iter.begin(); i != iter.end(); i += partition_size)

    {

      // If this chunk is free

      if (i == freed_iter)

      {

        // Increment freed_iter to point to next in free list

        freed_iter = nextof(freed_iter);

 

        // Continue searching chunks in the memory block

        continue;

      }

 

      // This chunk is not free (allocated), so call its destructor

      static_cast<T *>(static_cast<void *>(i))->~T();

      // and continue searching chunks in the memory block

    }

 

    // free storage

    UserAllocator::free(iter.begin());

 

    // increment iter

    iter = next;

  } while (iter.valid());

 

  // Make the block list empty so that the inherited destructor doesn't try to

  //  free it again.

  this->list.invalidate();

}

 

 

}//namespace kimi_boost

 

 

 

 

#endif//__KIMI_BOOST_POOL

Test code

 

void pool_test()

{

       using namespace std;

 

       {

              kimi_boost::object_pool<string> p;

              string* pi[100];

              for (int i = 0; i < 100; ++i)

              {

                     pi[i]= p.construct();

              }

              pi[1]->push_back('d');

              for (int i = 0; i < 100; ++i)

              {

                     p.destroy(pi[i]);

              }

              pi[2]->push_back('a');

 

             

              string* pstring = p.construct();

              bool isfrom = p.is_from(pstring);

              isfrom = p.is_from( pstring + 100 );

              p.destroy(pstring);

       }

       {

              kimi_boost::pool<> p(sizeof(int));

              int* pi[100];

              for (int i = 0; i < 100; ++i)

              {

                     pi[i]= (int*)p.malloc();

              }

 

              for (int i = 0; i < 100; ++i)

              {

                     p.free(pi[i]);

              }

       }

 

 

       {

              kimi_boost::pool<> p(sizeof(char));

              char* pstr = (char*)p.ordered_malloc(20);

              memset(pstr,'/0',20);

              p.ordered_free(pstr,20);

 

       }

}

Output

none

### .gnu_debugaltlink ELF Section Purpose The `.gnu_debugaltlink` section serves a specific role within the context of debugging information management in ELF (Executable and Linkable Format) binaries. This section contains two pieces of data that are crucial for alternative debug symbol handling: - The name of an alternate external debug file. - A build ID, which uniquely identifies the binary. This allows tools to locate separate debug files when performing operations such as symbolic debugging or analysis without bloating the main executable with extensive debug symbols[^2]. ### Usage in Debugging Process When using this feature, developers can strip out large amounts of debug information from executables while retaining references to where full details reside externally. During runtime or post-mortem analyses, specialized software like `gdb`, upon encountering a stripped binary equipped with a `.gnu_debugaltlink` entry, will automatically attempt to fetch corresponding detailed records based on provided paths and identifiers specified here. For instance, consider a scenario involving optimized production builds wherein minimizing footprint is essential; placing verbose but less frequently accessed metadata into segregated locations becomes beneficial both performance-wise and storage-efficiently. ```bash objcopy --only-keep-debug program program.debug # Extracts all debug info into 'program.debug' strip --remove-section=.debug_info program # Removes standard debug sections from original readelf -S program # Verifies presence of '.gnu_debugaltlink' after processing ``` By executing these commands sequentially, one effectively relocates comprehensive diagnostic resources yet maintains necessary linkages through mechanisms supported by modern toolchains.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值