使用者定義的記憶體管理
malloc()
經常呼叫底層作業系統函式來獲取記憶體頁面。但是這個函式並沒有什麼特別的,它可以通過宣告一個大的靜態陣列並從中分配來直接實現(確保正確對齊有一點點困難,實際上對齊到 8 個位元組幾乎總是足夠的)。
為了實現簡單的方案,控制塊儲存在緊接在從呼叫返回的指標之前的儲存器區域中。這意味著可以通過從返回的指標中減去並讀取控制資訊來實現 free()
,控制資訊通常是塊大小加上允許將其放回空閒列表中的一些資訊 - 未分配塊的連結列表。
當使用者請求分配時,搜尋空閒列表,直到找到與所請求的數量相同或更大的塊,然後在必要時將其拆分。如果使用者不斷地進行許多分配並且不可預測的大小並且以不可預測的間隔(並非所有真實程式都像這樣,簡單的方案通常適用於小程式),這可能導致記憶體碎片。
/* typical control block */
struct block
{
size_t size; /* size of block */
struct block *next; /* next block in free list */
struct block *prev; /* back pointer to previous block in memory */
void *padding; /* need 16 bytes to make multiple of 8 */
}
static struct block arena[10000]; /* allocate from here */
static struct block *firstfree;
許多程式需要大量分配相同大小的小物件。這很容易實現。只需使用帶有下一個指標的塊。因此,如果需要 32 位元組的塊:
union block
{
union block * next;
unsigned char payload[32];
}
static union block arena[100];
static union block * head;
void init(void)
{
int i;
for (i = 0; i < 100 - 1; i++)
arena[i].next = &arena[i + 1];
arena[i].next = 0; /* last one, null */
head = &block[0];
}
void *block_alloc()
{
void *answer = head;
if (answer)
head = head->next;
return answer;
}
void block_free(void *ptr)
{
union block *block = ptr;
block->next = head;
head - block;
}
該方案非常快速和有效,並且可以在一定的清晰度下變得通用。