慮到小型區塊可能造成的記憶體破碎問題,sgi 為此設計了雙層級配置器。當配置區塊超過 128bytes 時,稱為足夠大,使用第一級配置器,直接使用 malloc() 和 free()。當配置區塊不大於 128bytes 時,為了降低額外負擔,直接使用第二級配置器,採用複雜的 memory pool 處理方式。
整個設計究竟只開放第一級配置器,或是同時開放第二級配置器,取決於巨集 __use_malloc 是否被定義。
無論 alloc 被定義為第一級或第二級配置器,sgi 還為它再封裝乙個介面如下,使配置器的介面能夠符合stl規格# ifdef __use_malloc..
./*__malloc_alloc_template 就是第一級配置器*/
typedef __malloc_alloc_template<
0> malloc_alloc;
typedef malloc_alloc alloc;
#else..
./*__default_alloc_template 就是第二級配置器*/
typedef __default_alloc_template<__node_allocator_threads,
0> alloc;
#endif
上面這內部四個成員函式其實都是單純的轉呼叫,呼叫傳遞給配置器的成員函式。sgi stl 容器全部使用這個******_alloc 介面。template
<
class
_tp,
class
_alloc
>
class
******_alloc
static _tp*
allocate
(void
)static
void
deallocate
(_tp* __p, size_t __n)
static
void
deallocate
(_tp* __p)
};
下面是簡化後的一級配置器偽**
allocate()template
<
int __inst>
class
__malloc_alloc_template
static
voiddeallocate
(void
* __p, size_t /* __n */
)//釋放空間
static
void
*reallocate
(void
* __p, size_t /* old_sz */
, size_t __new_sz)
//realloc
//一塊空間,同樣也是在realloc失敗時呼叫_s_oom_realloc。
//設定類似與c++ new handler的記憶體不足的處理程式
static
void(*
__set_malloc_handler
(void
(*__f)()
))()
};
reallocate()#define __throw_bad_alloc fprintf(stderr, "out of memory\n"); exit(1)
static
void
*allocate
(size_t __n)
#ifndef __stl_static_template_member_bug
template
<
int __inst>
void
(*__malloc_alloc_template<__inst>
::__malloc_alloc_oom_handler)()
=0;#endif
//記憶體不足處理例程,初值為0,待使用者自定義,考慮記憶體不足時的應變措施。
template
<
int __inst>
void
*__malloc_alloc_template<__inst>
::_s_oom_malloc
(size_t __n)
(*__my_malloc_handler)()
;//使用者有自定義(釋放記憶體),則進入相應的處理程式
__result =
malloc
(__n);if
(__result)
return
(__result);}
//不斷的嘗試釋放和配置是因為使用者不知道還需要釋放多少記憶體來滿足分配需求,只能逐步的釋放配置
}
deallocate()static
void
*reallocate
(void
* __p, size_t /* old_sz */
, size_t __new_sz)
template
<
int __inst>
void
* __malloc_alloc_template<__inst>
::_s_oom_realloc
(void
* __p, size_t __n)
(*__my_malloc_handler)()
; __result =
realloc
(__p, __n);if
(__result)
return
(__result);}
}
set_new_handler()static
void
deallocate
(void
* __p, size_t /* __n */
)
第一級配置器以 malloc(),free(),realloc() 等 c 函式執行實際的記憶體配置、釋放、重配置操作,因此,sgi 不能直接使用 c++ 的 set_new_handler(),必須**乙個類似的 set_malloc_handler()。
這個函式重新指定了記憶體分配異常處理函式,並返回原有的記憶體分配異常處理函式,即設定新處理例程的同時也儲存了原有的處理例程。回看原始碼中的 allocate() 和 reallocate() 函式中的使用者定義記憶體不足異常處理例程正是通過這裡來指定的。/*該函式接收乙個返回值為空,引數為空的函式指標作為引數,最後返回乙個返回值和引數均為空的函式指標*/
static
void(*
__set_malloc_handler
(void
(*__f)()
))()
sgi 第一級配置器的 allocate() 和 reallocate() 都是在呼叫 malloc() 和 realloc() 不成功後,改呼叫 _s_oom_malloc() 和 _s_oom_realloc()。後兩者都有內迴圈,不斷呼叫 「記憶體不足處理例程」,期望在某次呼叫之後,可以獲得足夠的記憶體來完成所需求的記憶體分配,如果 「記憶體不足處理例程」 並未被客端設定,_s_oom_malloc() 和 _s_oom_realloc() 便會呼叫 __throw_bad_alloc,丟出 bad_alloc 異常資訊。
STL 一級 二級空間配置器
內碎片 需要3位元組,系統分配4位元組,剩下的1位元組就是內碎片 外碎片 由於不斷申請記憶體和歸還記憶體使得記憶體中剩下很多小片段的記憶體,無法被利用 作用 1 提高 復用率,功能模組化。2 減少記憶體碎片問題。3 提高記憶體分配的效率。4 有記憶體不足時的應對措施。5 隱藏實際中對儲存空間的分配及...
STL二級空間配置器
stl的二級空間配置器類似於memory pool,但是並不是memory pool,因為stl的二級空間配置器只維護了16個free list,而且只是小於128byte大小的小區塊,大於128byte會呼叫一級空間配置器malloc。16個鍊錶放在陣列中,每乙個陣列所鏈的鍊錶代表大小相等的小區塊...
STL空間配置器 兩級空間配置器簡介
本篇主要是簡單介紹一下兩級空間配置器的思路,以及提前說一下new handler機制 sgi 設計了雙層級配置器,第一級配置器直接使用 malloc 和 free 第二級則視情況採用不同策略,並採用了複雜的記憶體池 memory pool 整理方式。alloc是我們使用的配置器.alloc可能被指定...