malloc的實現原理

2021-07-25 03:15:21 字數 3318 閱讀 9912

malloc()是

c語言中動態

儲存管理

的一組標準庫函式之一。其作用是在記憶體的動態儲存區中分配乙個長度為size的連續空間。其引數是乙個無符號整形數,

返回值是乙個指向所分配的連續儲存域的起始位址的指標。 

動態記憶體分配

就 是指在程式執行的過程中動態地分配或者**儲存空間的分配記憶體的方法。動態記憶體分配不像陣列等靜態記憶體分配方法那樣需要預先分配儲存空間,而是由系統根據 程式的需要即時分配,且分配的大小就是程式要求的大小。本文簡單介紹動態記憶體分配函式malloc()及幾種實現方法。 

1. 簡介 

malloc()是

c語言中動態儲存管理的一組標準庫函式之一。其作用是在記憶體的動態儲存區中分配乙個長度為size的連續空間。其引數是乙個無符號整形數,返回值是乙個指向所分配的連續儲存域的起始位址的指標。還有一點必須注意的是,當函式未能成功分配儲存空間(如

記憶體不足

)就會返回乙個null指標。所以在呼叫該函式時應該檢測返回值是否為null並執行相應的操作。 

2. 函式說明 

c語言的動態儲存管理由一組標準庫函式實現,其原型在標準檔案裡描述,需要用這些功能時應包含這個檔案。與動態儲存分 配有關的函式共有四個,其中就包括儲存分配函式malloc()。函式原型是:void *malloc (size_t n);這裡的size_t是標準庫里定義的乙個型別,它是乙個無符號整型。這個整型能夠滿足所有對儲存塊大小描述的需要,具體相當於哪個整型由具體的c系 統確定。malloc的返回值為(void *)型別(這是通用指標的乙個重要用途),它分配一片能存放大小為n的資料的儲存塊,返回對應的指標值;如果不能滿足申請(找不到能滿足要求的儲存塊)就 返回null。在使用時,應該把malloc的返回值轉換到特定指標型別,賦給乙個指標。 

注意,雖然這裡的儲存塊是通過動態分配得到的,但 是它的大小也是確定的,同樣不允許越界使用。例如上面程式段分配的塊裡能存n個雙精度資料,隨後的使用就必須在這個範圍內進行。越界使用動態分配的儲存 塊,尤其是越界賦值,可能引起非常嚴重的後果,通常會破壞程式的執行系統,可能造成本程式或者整個

計算機系統

垮台。 

下例是乙個動態分配的例子: 

#include

main() 

for (count=0;count〈10;count++) /*給陣列賦值*/ 

array[count]=count; 

for(count=0;count〈10;count++) /*列印陣列元素*/ 

printf("%2d",array[count]); 

} 上例中動態分配了10個整型儲存區域,然後進行賦值並列印。例中if((array(int *) malloc (10*sizeof(int)))==null)語句可以分為以下幾步: 

1)分配10個整型的連續儲存空間,並返回乙個指向其起始位址的整型指標 

2)把此整型指標位址賦給array 

3)檢測返回值是否為null 

3. malloc()工作機制 

malloc函式的實質體現在,它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足 使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳 給使用者,並將剩下的那塊(如果有的話)返回到連線表上。呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片 段,如果這時使用者申請乙個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢 查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊。 

4. malloc()在

作業系統

中的實現 

在 c 程式中,多次使用malloc () 和 free()。不過,您可能沒有用一些時間去思考它們在您的

作業系統

中是如何實現的。本節將向您展示 malloc 和 free 的乙個最簡化實現的**,來幫助說明管理記憶體時都涉及到了哪些事情。 

在大部分作業系統中,記憶體分配由以下兩個簡單的函式來處理: 

void *malloc (long numbytes):該函式負責分配 numbytes 大小的記憶體,並返回指向第乙個位元組的指標。 

void free(void *firstbyte):如果給定乙個由先前的 malloc 返回的指標,那麼該函式會將分配的空間歸還給程序的「空閒空間」。 

malloc_init 將是初始化記憶體分配程式的函式。它要完成以下三件事:將分配程式標識為已經初始化,找到系統中最後乙個有效

記憶體位址

,然後建立起指向我們管理的記憶體的指標。這三個變數都是

全域性變數

: 清單 1. 我們的簡單分配程式的全域性變數 

int has_initialized = 0; 

void *managed_memory_start; 

void *last_valid_address; 

如前所述,被對映的記憶體的邊界(最後乙個有效位址)常被稱為系統中斷點或者 當前中斷點。在很多 

unix

? 系統中,為了指出當前系統中斷點,必須使用 sbrk(0) 函式。 sbrk 根據引數中給出的位元組數移動當前系統中斷點,然後返回新的系統中斷點。使用引數 0 只是返回當前中斷點。這裡是我們的 malloc 初始化**,它將找到當前中斷點並初始化我們的變數: 

清單 2. 分配程式初始化函式 

/* include the sbrk function */ 

#include 

void malloc_init() 

現在,為了完全地管理記憶體,我們需要能夠追蹤要分配和**哪些記憶體。在對記憶體塊進行了 free 呼叫之後,我們需要做的是諸如將它們標記為未被使用的等事情,並且,在呼叫 malloc 時,我們要能夠定位未被使用的記憶體塊。因此, malloc 返回的每塊記憶體的起始處首先要有這個結構: 

清單 3. 記憶體控制塊結構定義 

struct mem_control_block ; 

現在,您可能會認為當程式呼叫 malloc 時這會引發問題 —— 它們如何知道這個結構?答案是它們不必知道;在返回指標之前,我們會將其移動到這個結構之後,把它隱藏起來。這使得返回的指標指向沒有用於任何其他用途的 記憶體。那樣,從呼叫程式的角度來看,它們所得到的全部是空閒的、開放的記憶體。然後,當通過 free() 將該指標傳遞回來時,我們只需要倒退幾個記憶體位元組就可以再次找到這個結構。 

在討論分配記憶體之前,我們將先討論釋放,因為它更簡單。為了釋放記憶體,我們必須要做的惟一一件事情就是,獲得我們給出的指標,回退 sizeof(struct mem_control_block) 個位元組,並將其標記為可用的。這裡是對應的**: 

清單 4. 解除分配函式 

malloc的實現原理

malloc是c語言最常用的標準庫函式之一,用於在程式執行中動態地申請記憶體空間。我們都會使用它,其函式原型為 extern void malloc unsigned int num bytes 那麼它是怎麼實現的呢?不同的編譯環境中對它的實現可能不同。比如glibc the gnu c libra...

malloc實現原理

malloc 是c語言中動態儲存管理 的一組標準庫函式之一。其作用是在記憶體的動態儲存區中分配乙個長度為size的連續空間。其引數是乙個無符號整形數,返回值 是乙個指向所分配的連續儲存域的起始位址的指標。動態記憶體分配 就 是指在程式執行的過程中動態地分配或者 儲存空間的分配記憶體的方法。動態記憶體...

malloc實現原理簡介

malloc 是c語言中動態儲存管理 的一組標準庫函式之一。其作用是在記憶體的動態儲存區中分配乙個長度為size的連續空間。其引數是乙個無符號整形數,返回值 是乙個指向所分配的連續儲存域的起始位址的指標。動態記憶體分配 就 是指在程式執行的過程中動態地分配或者 儲存空間的分配記憶體的方法。動態記憶體...