malloc、realloc、calloc的用法,作用,區別,及實現原理

先來看一下三個函數的聲明:

void * malloc(unsigned size);
void * realloc(void *ptr, unsigned newsize);
void * calloc(size_t numElements, size_t sizeofElement);

它們都包含在 #include <stdlib.h>頭文件中,他們的返回值都是請求分配的地址,如果請求失敗就返回NULL。

解釋一下這三個函數的用法、作用、區別。

malloc()
malloc()在內存的動態存儲區中分配一塊長度爲size字節的連續區域。參數size爲需要的內存空間的長度,返回該區域的地址
示例:
這裏寫圖片描述

這裏寫圖片描述

calloc()
calloc()與malloc相似,參數sizeofElement爲申請地址的單位元素長度,numElements爲參數個數
示例:
這裏寫圖片描述

這裏寫圖片描述

由於malloc可以很方便的實現calloc的功能,所以我們一般不去使用calloc。

realloc()
realloc()是給一個已經分配了地址的指針重新分配空間,參數ptr爲原有的空間地址,newsize是重新申請的地址空間
示例:
這裏寫圖片描述

這裏寫圖片描述

區別如下:

malloc不能初始化所分配的內存空間,而函數calloc能。如果malloc函數分配的內存空間原來沒有被使用過,則其中的每一位可能都是0;反之,如果這部分內存曾經被分配過,則其中可能遺留各種各樣的數據,也就是說,使用malloc函數的程序開始時(內存還沒有被重新分配)能正常進行,但經過一段時間(內存已經被重新分配,可能會出現一些問題)。

calloc會將所分配的空間中的每一位都初始化爲零,也就是說如果你是字符類型或整數類型的元素分配內存,那麼這些元素將保證會被動的初始化爲0,如果你爲指針類型的元素分配內存,那麼這些元素通常會被初始化爲空指針。如果你爲實型元素分配內存,則這些元素會被初始化爲浮點型的0。

realloc可以對給定的指針所指向的空間進行擴大或縮小,無論是擴大還是縮小,原有的內存中的內容將保持不變,當然,對於縮小,則被縮小的那一部分的內容將會丟失,realloc並不保持調整後的內存空間和原來的 內存空間保持同一內存地址,realloc返回的指針很可能指向新的地址。

實現原理

malloc、calloc函數的實質體現在,它有一個將可用的內存連接爲一個長長的鏈表(即所謂的空閒鏈表)。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內存塊,然後將該內存塊一分爲二(一塊的大小與用戶申請的大小一樣,另一塊就是剩下的字節),接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(如果有的話),返回到鏈表上,調用free函數 時,它將用戶釋放的內存塊連接到空鏈上,到最後,空閒鏈表會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那麼空閒鏈上可能沒有可能滿足用戶要求的片段了,於是malloc函數請求延時,並開始在空間中翻箱倒櫃的檢查內存片段,對它們進行整理,並將相鄰的小空閒塊合成較大的內存塊

realloc是從堆空間上分配內存,當擴大一塊內存空間時,realloc試圖直接從現存的數據後面的哪些字節中獲得附加的字節,如果能夠滿足,自然天下太平,那麼如果後面的字節不夠,問題就來了,那麼就使用堆上第一個足夠滿足要求的自由空間塊,現存的數據然後就被拷貝到新的位置上,而老塊則放回堆空間,這句話傳遞的一個很重要的信息就是數據可能被移動。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章