1. 程式人生 > >STL初探——第一級配置 __malloc_alloc_template的學習心得

STL初探——第一級配置 __malloc_alloc_template的學習心得

exception template 定義 stl 空間 似的 strong cep 對象

  在第一級配置器中,一開始就定義了內存分配出錯的宏接口,如下:

#ifndef __THROW_BAD_ALLOC
#  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
#    include <stdio.h>
#    include <stdlib.h>
#    define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
#  else /* Standard conforming out-of-memory handling 
*/ # include <new> # define __THROW_BAD_ALLOC throw std::bad_alloc() # endif #endif

  先弄清楚第一級配置器如何工作,註意沒有template型別參數,因為我們只是分配空間,並不進行對象的構造,至於非型別參數 "__inst" ,就沒怎麽派上用場,如下:

template <int __inst>          
class __malloc_alloc_template {

private:                 
//以下函數是處理內存不足的情況
  static
void* _S_oom_malloc(size_t); static void* _S_oom_realloc(void*, size_t); #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG //無法處理模板類中的靜態成員 static void (* __malloc_alloc_oom_handler)(); #endif public: static void* allocate(size_t __n) { void* __result = malloc(__n); if (0 == __result) __result = _S_oom_malloc(__n); //分配的內存無法滿足需求時,調用_S_oom_malloc()函數
return __result; }   //內存釋放函數 static void deallocate(void* __p, size_t /* __n */) { free(__p); }   //內存重配置函數 static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz) { void* __result = realloc(__p, __new_sz); if (0 == __result) __result = _S_oom_realloc(__p, __new_sz); return __result; }   //你可以通過該函數指定自己的 out-of-memory handler static void (* __set_malloc_handler(void (*__f)()))() { void (* __old)() = __malloc_alloc_oom_handler; __malloc_alloc_oom_handler = __f; return(__old); }
};
// malloc_alloc out-of-memory handling #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG template <int __inst> void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0; #endif template <int __inst> void* __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n) { void (* __my_malloc_handler)(); void* __result; for (;;) {                                //和_S_oom_realloc類似                         __my_malloc_handler = __malloc_alloc_oom_handler; if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; } (*__my_malloc_handler)(); __result = malloc(__n); if (__result) return(__result); } } template <int __inst> void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n) { void (* __my_malloc_handler)(); void* __result; for (;;) {                       //不斷嘗試釋放,配置,再釋放,再配置.... __my_malloc_handler = __malloc_alloc_oom_handler;     if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; } (*__my_malloc_handler)();                  //調用處理函數,企圖釋放內存,處理函數是客端定義 __result = realloc(__p, __n);                //再次嘗試釋放內存 if (__result) return(__result); } }

  第一級配置器以 malloc()、free()、realloc()等 C 函數執行實際的內存配置、釋放、重配置操作,並實現出類似 C++ new-handler 的機制,不過並不能直接使用 C++ new-handler 機制, 因為其並非使用 ::operator new 來配置內存。

  C++ new-handler 機制是,可以要求系統在配置需求無法被滿足時,調用你所指定的函數。一旦 ::operator new 無法完成任務,在丟出 std::bad_alloc 異常狀態之前,會先調用由客端指定的處理例程,該處理例程通常被稱為new-handler。

  《effective C++ handler》 中介紹了 new-handler 的內存不足處理模式,詳情見下篇。

  SGI 以malloc 而非 ::operator new 來配置內存,原因是C++並未提供相應於 realloc() 的內存配置操作,當然不排除還有些歷史因素。因此,SGI 不能使用 C++ 的 set_new_handler() ,必需仿真一個類似類似的 set_new_handler().

  SGI 第一級配置器 allocate() 和 realloc() 都是在調用 malloc() 和 realloc() 不成功後,改調用 oom_malloc() 和 oom_realloc()。後兩者都有死循環,不斷調用 "內存不足處理例程" ,期望在某次調用的時候,能夠得到充足的內存分配而完成任務。但如果“內存不足處理例程”並沒有被客端設定, oom_malloc() 和 oom_realloc() 便會直接調用 __THROW_BAD_ALLOC,丟出 bad_alloc 異常信息,或利用 exit(1)終止程序。

  

STL初探——第一級配置 __malloc_alloc_template的學習心得