程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++內存管理變革(4): boost::object_pool

C++內存管理變革(4): boost::object_pool

編輯:關於C++

言歸正傳。我們在內存池(MemPool)技術詳解已經介紹了boost::pool組件。從內存管理觀念的變革來看,這是是一個傳統的MemPool組件,盡管也有一定的改進(但只是性能上的改進)。但boost::object_pool不同,它與我在C++內存管理變革強調的觀念非常吻合。可以認為,boost::object_pool是一種不通用的gc allocator組件。

我已經多次提出gc allocator的概念。這裡仍然需要強調一下,所謂gc allocator,是指具垃圾回收能力的allocator。C++內存管理變革(1) 中我們引入了這個概念,但是沒有明確gc allocator一詞。

boost: object_pool內存管理觀念

boost::object_pool的了不起之處在於,這是C++從庫的層次上頭一次承認,程序員在內存管理上是會犯錯誤的,由程序員來確保內存不洩漏是困難的。boost::object_pool允許你忘記釋放內存。我們來看一個例子:

class X { … };

    void func()
    {
        boost::object_pool<X> alloc;

        X* obj1 = alloc.construct();
        X* obj2 = alloc.construct();
        alloc.destroy(obj2);
    }

如果boost::object_pool只是一個普通的allocator,那麼這段代碼顯然存在問題,因為obj1的析構函數沒有執行,申請的內存也沒有釋放。

但是這段代碼是完全正常的。是的,obj1的析構確實執行了,所申請內存也被釋放了。這就是說,boost::object_pool既支持你手工釋放內存(通過主動調用object_pool::destroy),也支持內存的自動回收(通過object_pool::~object_pool析構的執行)。這正符合gc allocator的規格。

注:內存管理更好的說法是對象管理。內存的申請和釋放更確切的說是對象的創建和銷毀。但是這裡我們不刻意區分這兩者的差異。

boost: object_pool與AutoFreeAlloc

我們知道,AutoFreeAlloc不支持手工釋放,而只能等到AutoFreeAlloc對象析構的時候一次性全部釋放內存。那麼,是否可以認為boost::object_pool是否比AutoFreeAlloc更加完備呢?

其實不然。boost::object_pool與AutoFreeAlloc都不是完整意義上的gc allocator。AutoFreeAlloc因為它只能一次性釋放,故此僅僅適用特定的用況。然而盡管AutoFreeAlloc不是普適的,但它是通用型的gc allocator。而boost::object_pool只能管理一種對象,並不是通用型的allocator,局限性其實更強。

boost: object_pool的實現細節

大家對boost::object_pool應該已經有了一個總體的把握。現在,讓我們深入到object_pool的實現細節中去。

在內存池(MemPool)技術詳解中,我們介紹boost::pool組件時,特意提醒大家留意pool::ordered_malloc/ordered_free函數。事實上,boost::object_pool的malloc/construct, free/destroy函數調用了pool::ordered_malloc, ordered_free函數,而不是pool::malloc, free函數。

讓我們解釋下為什麼。

其實這其中的關鍵,在於object_pool要支持手工釋放內存和自動回收內存(並自動執行析構函數)兩種模式。如果沒有自動析構,那麼普通的MemPool就足夠了,也就不需要ordered_free。既然有自動回收,同時又存在手工釋放,那麼就需要區分內存塊(MemBlock)中哪些結點(Node)是自由內存結點(FreeNode),哪些結點是已經使用的。對於哪些已經是自由內存的結點,顯然不能再調用對象的析構函數。

我們來看看object_pool::~object_pool函數的實現:

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

這段代碼不難理解,object_pool遍歷所有申請的內存塊(MemBlock),並遍歷其中所有結點(Node),如果該結點不出現在自由內存結點(FreeNode)的列表(FreeNodeList)中,那麼,它就是用戶未主動釋放的結點,需要進行相應的析構操作。

現在你明白了,ordered_malloc是為了讓MemBlockList中的MemBlock有序,ordered_free是為了讓FreeNodeList中的所有FreeNode有序。而MemBlockList, FreeNodeList有序,是為了更快地檢測Node是自由的還是被使用的(這實際上是一個集合求交的流程,建議你看看std::set_intersection,它定義在STL的<algorithm>中)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved