malloc函式與realloc函式

2021-05-25 23:09:14 字數 3455 閱讀 7627

malloc函式與realloc函式(動態儲存必備)

malloc函式

malloc函式簡介

原型:extern void *malloc(unsigned int num_bytes);

標頭檔案:#include 或 #include (注意:alloc.h 與 malloc.h 的內容是完全一致的。)

功能:分配長度為num_bytes位元組的記憶體塊

說明:如果分配成功則返回指向被分配記憶體的指標,否則返回空指標null。

當記憶體不再使用時,應使用free()函式將記憶體塊釋放。

舉例說明

/*malloc.c*/

#include

#include

main()

函式宣告(函式原型):

void *malloc(int size);

說明:malloc 向系統申請分配指定size個位元組的記憶體空間。返回型別是 void* 型別。void* 表示未確定型別的指標。c,c++規定,void* 型別可以強制轉換為任何其它型別的指標。

從函式宣告上可以看出。malloc 和 new 至少有兩個不同: new 返回指定型別的指標,並且可以自動計算所需要大小。比如:

int *p;

p = new int; //返回型別為int* 型別(整數型指標),分配大小為 sizeof(int);

或: int* parr;

parr = new int [100]; //返回型別為 int* 型別(整數型指標),分配大小為 sizeof(int) * 100;

而 malloc 則必須由我們計算要位元組數,並且在返回後強行轉換為實際型別的指標。

int* p;

p = (int *) malloc (sizeof(int));

第一、malloc 函式返回的是 void * 型別,如果你寫成:p = malloc (sizeof(int)); 則程式無法通過編譯,報錯:「不能將 void* 賦值給 int * 型別變數」。所以必須通過 (int *) 來將強制轉換。

第二、函式的實參為 sizeof(int) ,用於指明乙個整型資料需要的大小。如果你寫成:

int* p = (int *) malloc (1);

**也能通過編譯,但事實上只分配了1個位元組大小的記憶體空間,當你往裡頭存入乙個整數,就會有3個位元組無家可歸,而直接「住進鄰居家」!造成的結果是後面的記憶體中原有資料內容全部被清空。

malloc 也可以達到 new 的效果,申請出一段連續的記憶體,方法無非是指定你所需要記憶體大小。

比如想分配100個int型別的空間:

int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100個整數的記憶體空間。

另外有一點不能直接看出的區別是,malloc 只管分配記憶體,並不能對所得的記憶體進行初始化,所以得到的一片新記憶體中,其值將是隨機的。

除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指標,在其它操作上保持一致。

對其做乙個特例補充

char *ptr;

if ((ptr = (char *)malloc(0)) == null)

puts("got a null pointer");

else

puts("got a valid pointer");

此時得到的是got a valid pointer。把0賦給malloc能得到乙個合法的指標。

malloc()函式的工作機制

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

realloc函式

原型:extern void *realloc(void *mem_address, unsigned int newsize);

用法:#include 有些編譯器需要#include

功能:改變mem_address所指記憶體區域的大小為newsize長度。

說明:如果重新分配成功則返回指向被分配記憶體的指標,否則返回空指標null。

當記憶體不再使用時,應使用free()函式將記憶體塊釋放。

注意:這裡原始記憶體中的資料還是保持不變的。

舉例:// realloc.c

#include

#include

main()

詳細說明及注意要點:

1、如果有足夠空間用於擴大mem_address指向的記憶體塊,則分配額外記憶體,並返回mem_address

這裡說的是「擴大」,我們知道,realloc是從堆上分配記憶體的,當擴大一塊記憶體空間時, realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得附加的位元組,如果能夠滿足,自然天下太平。也就是說,如果原先的記憶體大小後面還有足夠的空閒空間用來分配,加上原來的空間大小= newsize。那麼就ok。得到的是一塊連續的記憶體。

2、如果原先的記憶體大小後面沒有足夠的空閒空間用來分配,那麼從堆中另外找一塊newsize大小的記憶體。

並把原來大小記憶體空間中的內容複製到newsize中。返回新的mem_address指標。(資料被移動了)。

老塊被放回堆上。

例如:#include

void main()

在這段程式中我們增加了指標q,用它記錄了原來的記憶體位址p。這段程式可以編譯通過,但在執行到a行時,如果原有記憶體後面沒有足夠空間將原有空間擴充套件成乙個連續的新大小的話,realloc函式就會以第二種方式分配記憶體,此時資料發生了移動,那麼所記錄的原來的記憶體位址q所指向的記憶體空間實際上已經放回到堆上了!這樣就會產生q指標的指標懸掛,如果再用q指標進行操作就可能發生意想不到的問題。所以在應用realloc函式是應當格外注意這種情況。

3、返回情況

返回的是乙個void型別的指標,呼叫成功。(這就再你需要的時候進行強制型別轉換)

返回null,當需要擴充套件的大小(第二個引數)為0並且第乙個引數不為null,此時原記憶體變成了「freed(游離)」的了。

返回null,當沒有足夠的空間可供擴充套件的時候,此時,原記憶體空間的大小維持不變。

4、特殊情況

如果mem_address為null,則realloc()和malloc()類似。分配乙個newsize的記憶體塊,返回乙個指向該記憶體塊的指標。

如果newsize大小為0,那麼釋放mem_address指向的記憶體,並返回null。

如果沒有足夠可用的記憶體用來完成重新分配(擴大原來的記憶體塊或者分配新的記憶體塊),則返回null.而原來的記憶體塊保持不變。

malloc與free函式用法

在c裡,記憶體管理是通過專門的函式來實現。另外,為了相容各種程式語言,作業系統提供的介面通常是c 語言寫成的函式宣告 windows 本身也由c和組合語言寫成 1分配記憶體malloc函式 需要包含標頭檔案 include 函式宣告 函式原型 void malloc int size 說明 mall...

C語言 malloc 函式與alloc 函式

c語言跟記憶體分配方式 1 從靜態儲存區域分配。內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。例如全域性變數,static變數。2 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集...

庫函式之malloc與new

從本質上來說,malloc linux上具體實現可以參考man malloc,glibc通過brk mmap 實現 是libc裡面實現的乙個函式,如果在source code中沒有直接或者間接include過stdlib.h,那麼gcc就會報出error malloc was not declare...