オペレーティングシステムは、API呼び出しを提供して、切り分けて呼び出し元に提供できるメモリのブロックを割り当てますmalloc
。Linux / unixでは、を見てくださいsbrk
。Windowsでは、Win32ヒープAPIを確認してください。あなたの記録はこのブロックを指します。ブロックの2つの割り当てられたセクションが重複しないようにすることは、アロケータコードの仕事です。
あなたの記録は無料のリストを実装しているようです。では、アロケータが(まだ)ない場合、リストノードをどのように割り当てるのでしょうか。通常の解決策は、空きブロック自体でそれを行うことです。したがって、フリーブロックの構造は次のとおりです。
typedef struct free_block {
struct free_block *next, *prev;
size_t size;
unsigned char buffer[1];
} FREE_BLOCK;
現在、このデータ構造は実際には空きブロックの先頭にあります。そのバッファの宣言には1バイトしかありませんが、実際のバッファはsize
バイトです。最初は次のようなものがあります。
static FREE_BLOCK *free_list = sbrk(ARENA_SIZE);
free_list->next = free_list->prev = free_list;
free_list->size = ARENA_SIZE - offsetof(FREEBLOCK, buffer);
これにより、アリーナ全体が1つのブロックとしてフリーリストに追加されます。アロケータはfree_list
、十分な大きさのブロックを検索し、必要な部分を切り分け、残りの小さなブロック(存在する場合)をフリーリストに戻します。解放するために、解放されたブロックをリストに追加し、隣接するブロックを合体させます。
単純なフリーリストアロケータは、割り当てるフリーブロックの選択方法が異なります。ファーストフィット、ローテーションファーストフィット、ベストフィット、ワーストフィットなどです。実際には、ローテーションファーストフィットは他のどのブロックよりもうまく機能するようです。
ちなみに、フリーリストで実装される一般的なアルゴリズムはすべて、二重リンクを必要としません。単一のもので十分です。
これは学術的な課題であるためmalloc
、アロケータが管理する大きなブロック(「アリーナ」と呼ばれることが多い)を確立するために(オペレーティングシステムAPIの代わりに)呼び出すだけで問題ありません。バイトの大きな配列を宣言することもできます。