ヘッダファイル <記憶>
STD :: 1.1割り当て、STD :: DEALLOCATE (による:: new演算子と::演算子削除パッケージは実装)
STD :: 1.2、構築STD :: Destoryはを (で配置新しい実装とデストラクタを呼び出します)
テンプレート<クラスT1、T2クラス> インラインボイドh_construct(T1 * P、CONST T2&値) { 新しい(P)T1(値)。 } テンプレート<クラスT> インライン無効h_destroy(T *ポインタ) { pointer->〜T(); }
1.3のstd ::のalloc
STLのを考慮に入れて、小さなメモリブロックの問題は、2つの問題がある:1)原因メモリの断片化
2)追加負担(メモリのブロックを得るために、より小さな管理ブロックのための追加スペースの必要性、大きな追加の負担割合)
二重レベルの設定、直接第一段構成のデザインのmalloc()とfree()を、第二段階は、構成面積がより大きい場合に、異なる戦略を用いた場合のように配置されている128バイト、第一段階のダイレクトコールが配置されています。アロケーションブロックがより少ない場合128バイト使用しながら、それを第一段構成の助けを借りずに、メモリ・プールを達成します。どのような第一段階の使用であるか、または配置された第2のステージは、マクロ定義を制御するように構成されています。SGIのSTLは、デフォルト設定では、第二段階です。
セカンドレベルの設定は維持 16 のGe 、フリーリストの各サイズの管理8,16,24 ... 120,128bytes の小ブロックを。
フリー・リスト、組合を介してリンクされたリストを構成する第1フィールドを管理ノードポインタの追加の負担を解決するために、次のように構成されているノード、第2のフィールド実際のブロックに
組合OBJ { 組合OBJ * free_list_link。 チャーたclient_data [1]。/ *クライアントはこれを見ています。* / }。
クラス構造
クラスh_alloc { プライベート: 列挙型{ ALIGN = 8、//アライメント境界 MAX_BYTES = 128、//上限 NFREELISTS = MAX_BYTES / ALIGN //数 }。 フリーブロックリストノード構造に対応した労働組合のOBJ {// 組合OBJ * free_list_link。 チャーたclient_data [1]。/ *クライアントはこれを見ています。* / }。 プライベート: 静的size_tのROUND_UP(size_tのバイト)//アライメント機能 { リターン(((バイト)+(size_tの)ALIGN - 1)&〜((size_tの)ALIGN - 1)); } // n番目のチェーンを用いた演算、nは0〜 freeList_index size_tの静的(size_tのバイト) { リターン(((バイト)+(size_tの)ALIGN - 1)/(size_tの)ALIGN - 1)。 } //は、サイズnのオブジェクトを返し、およびサイズの他のブロックにN free_listに添加してもよいです 静的な無効*リフィルは(size_t N); サイズサイズのブロックのnobjsを収容することができます。//バルク・コンフィギュレーション・スペース 静的のchar * chunk_alloc(size_tのサイズ、INT&nobjs)。 パブリック: 静的ボイド*割り当ては(size_t N); 静的な無効DEALLOCATE(void *型のp、size_tのN)。 //静的な無効* REALLOCATE(void *型のp、size_tのold_sz、size_tのnew_sz)。 プライベート: 静的OBJ *揮発性m_free_list [NFREELISTS]; // 16个フリーリスト 静的のchar * m_start_free; //開始位置メモリプール、chunk_allocの変化のみ()内 静的のchar * m_end_free; //終了位置メモリプール、のみchunk_allocの変更() 静的size_tののm_heap_size。 }。 char * h_alloc :: m_start_free = 0; char * h_alloc :: m_end_free = 0; size_tのh_alloc :: m_heap_size = 0; 型名h_alloc :: OBJ *揮発性h_alloc :: m_free_list [NFREELISTS]。
1)()関数を割り当てます
void *型h_alloc ::は(size_t n)を割り当てます { OBJ *揮発性*のmy_free_list。 OBJ *結果。 //(MAX_BYTES> N)場合には最初の段階は、128バイトコンフィギュレータより大きい呼び出し { リターン(malloc関数(N))。 } 他 { //適した16自由なリストを見つけます my_free_list = m_free_list + freeList_index(N) 結果= * my_free_list。 もし(結果== 0) { // free_list利用できる、詰め替えfree_listを見つけられませんでした ボイド* R =リフィル(ROUND_UP(N))。 Rを返します。 } // free_listを調整 * my_free_list = result-> free_list_link。 結果を返します。 } }
2))(解放
空h_alloc :: DEALLOCATE(void *型のp、size_tのN) { OBJ * Q =(OBJ *)P。 OBJ *揮発性*のmy_free_list。 IF(N> MAX_BYTES) { 無料(Q); リターン; } 対応free_listを//検索します my_free_list = m_free_list + freeList_index(N) // free_list、リカバリブロックを調整 q->free_list_link = *my_free_list; *my_free_list = q; }
3) refill()
填充自由链表用,缺省一次取20个新节点,具体看内存池大小
void* h_alloc::refill(size_t n) { int nobjs = 20; //默认取20个节点 char* chunck = chunk_alloc(n, nobjs);//从内存池申请内存 if (nobjs == 1) { return chunck; // 如果只申请到一个节点,不用调整free_list,直接返回 } obj* volatile * m_free_list = m_free_list + freeList_index(n); //找到n号链表 obj* result = (obj*)chunck; // 保存要返回的结果 obj* next_obj = (obj*)(chunck + n); *m_free_list = next_obj; //链表第一个节点 // 串联各个节点,第一个节点已经返回出去了 obj* current_objs; for (int i = 1; ;i++) { current_objs = next_obj; if (nobjs - 1 == i) { current_objs->free_list_link = 0; break; } else { next_obj = (obj*)(next_obj + n); current_objs->free_list_link = next_obj; } } return result; }
4) chunk_alloc()
从内存池取空间给refill函数,内存池不够,从堆空间获取内存给内存池
char* h_alloc::chunk_alloc(size_t size, int& nobjs) { size_t total_bytes = size * nobjs; size_t left_bytes = m_end_free - m_start_free; char* result; if(left_bytes > total_bytes) //内存池剩余空间满足需求量 { result = m_start_free; m_start_free += total_bytes; return result; } else if (left_bytes > size) //内存池剩余空间不满足需求量,但是足够一个以上的区块 { nobjs = left_bytes / size; total_bytes = nobjs * size; result = m_start_free; m_start_free += total_bytes; return result; } else //内存池大小不够一个区块 { size_t bytes_to_get = 2 * total_bytes + round_up(m_heap_size >> 4); //size_t bytes_to_get = 2 * total_bytes; if (left_bytes > 0) //残余零头不浪费 { obj* volatile * m_free_list = m_free_list + freeList_index(left_bytes); //找到n号链表 ((obj*)m_start_free)->free_list_link = *m_free_list; *m_free_list = (obj*)m_start_free; } //申请堆空间 m_start_free = (char*)malloc (bytes_to_get); if (0 == m_start_free) { printf("chunk_alloc malloc failed\n"); //申请失败处理,省略。。。 } m_heap_size += bytes_to_get; m_end_free = m_start_free + bytes_to_get; //递归调用,修正nobjs return (chunk_alloc(size, nobjs)); } }