STL容器可以儲存任何C++語言支援的基本類型、使用者自訂類型的對象。容器本身只是實現了一種資料結構,對使用者資料進行管理。使用者資料最終都是儲存在記憶體中的,那麼記憶體的申請、釋放工作是由“空間配置器”承擔的。標準c++中都提供了std::allocator類。
當容器中儲存的是使用者自訂類型資料時,有的資料類型結構簡單,佔用的空間小;而有的資料類型結構複雜,需要的記憶體空間大。有的應用程式,需要頻繁的進行資料元素的插入、刪除操作,這就對應這頻繁的記憶體空間的申請、釋放工作。大家都知道頻繁的記憶體操作,會產生嚴重的效能問題。為瞭解決這些問題,stlport提供了兩個空間配置器。一個是“簡單空間配置器”,只是對c執行階段程式庫中malloc/free函數進行了簡單的封裝,唯一不同的是,提供類似new異常處理機制。另一個是“基於記憶體池的空間配置器”,容器每次申請記憶體的時候,空間配置器會基於一定的策略,向os申請交大的記憶體,避免每次記憶體申請都向os申請。
這篇文章,只是介紹“簡單空間配置器”。簡單空間配置器,只是對 malloc/free進行簡單的封裝。在記憶體配置的時候,有可能記憶體耗盡,而申請失敗。所以向使用者提供了一個例外處理常式的註冊常式,具體實現如下:
typedef void (*oom_malloc_handler)();
static oom_malloc_handler set_oom_malloc_handler(oom_malloc_handler handler)
{
oom_malloc_handler old = _oom_malloc_handler;
_oom_malloc_handler = handler;
return old;
}
如果申請記憶體失敗了,那我們就會不停的調用 _oom_malloc_handler ,期盼著通過調用 _oom_malloc_handler ,會得到一部分記憶體,然後在重新分配,直到分配到記憶體、或者使用者將 _oom_malloc_handler 設定為0為之。具體實現如下:
static void* allocate(size_t size)<br /> {<br /> void* pResult = malloc(size);<br /> if ( !pResult )<br /> {<br /> for ( ; ; )<br /> {<br /> /**<br /> * 如果使用者沒有提供記憶體配置例外處理常式,那麼直接結束進程。<br /> */<br /> if ( !_oom_malloc_handler )<br /> {<br /> exit(1);<br /> }</p><p> //調用例外處理常式,然後重新分配記憶體。其實這裡是渴望使用者能釋放記憶體。<br /> _oom_malloc_handler();<br /> pResult = malloc(size);<br /> if (pResult)<br /> {<br /> return pResult;<br /> }<br /> }<br /> }<br /> return pResult;<br /> }<br />
使用者在編寫例外處理常式時,應該通過一定機制,使得_oom_malloc_handler 可以為0,否則程式就無限期的執行下去了。
程式完整的代碼:
檔案名稱:
//bbg_simple_alloc.h
#ifndef _BBG_SIMPLE_ALLOC_H_<br />#define _BBG_SIMPLE_ALLOC_H_</p><p>#include "../bbg_common/bbg_common.h"<br />#include <cstdlib></p><p>BEGIN_BBG</p><p>class simple_alloc<br />{<br />public:<br /> typedef void (*oom_malloc_handler)();<br />public:<br /> static void* allocate(size_t size)<br /> {<br /> void* pResult = malloc(size);<br /> if ( !pResult )<br /> {<br /> for ( ; ; )<br /> {<br /> /**<br /> * 如果使用者沒有提供記憶體配置例外處理常式,那麼直接結束進程。<br /> */<br /> if ( !_oom_malloc_handler )<br /> {<br /> exit(1);<br /> }</p><p> //調用例外處理常式,然後重新分配記憶體。其實這裡是渴望使用者能釋放記憶體。<br /> _oom_malloc_handler();<br /> pResult = malloc(size);<br /> if (pResult)<br /> {<br /> return pResult;<br /> }<br /> }<br /> }<br /> return pResult;<br /> }</p><p> static void deallocate(void* p , size_t n)<br /> {<br /> BBG_UNUSED(n);<br /> free(p);<br /> }</p><p> static oom_malloc_handler set_oom_malloc_handler(oom_malloc_handler handler)<br /> {<br /> oom_malloc_handler old = _oom_malloc_handler;<br /> _oom_malloc_handler = handler;<br /> return old;<br /> }<br />private:</p><p> simple_alloc();<br /> ~simple_alloc();<br />private:<br /> static oom_malloc_handler _oom_malloc_handler;<br />};</p><p>simple_alloc::oom_malloc_handler simple_alloc::_oom_malloc_handler = 0;<br />END_BBG<br />#endif//_BBG_SIMPLE_ALLOC_H_<br />