malloc函式的用法
malloc函式是一種分配長度為num_bytes位元組的記憶體塊的函式,可以向系統申請分配指定size個位元組的記憶體空間。malloc的全稱是memory allocation(動態記憶體分配),當無法知道記憶體具體位置的時候,想要繫結真正的記憶體空間,就需要用到動態的分配記憶體。返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可以通過型別轉換強制轉換為任何其它型別的指標。
1、函式原型及說明
void *malloc(long NumBytes):該函式分配了NumBytes個位元組,並返回了指向這塊記憶體的指標。如果分配失敗,則返回一個空指標(NULL)。分配失敗的原因,應該有多種比如說空間不足就是一種。
void free(void *FirstByte): 該函式是將之前用malloc分配的空間還給程式或者是作業系統,也就是釋放了這塊記憶體,讓它重新得到自由。
2、函式的用法
使用前要申明:#include <stdlib.h>或者#include <malloc.h>
如果在source code中沒有直接或者間接include過stdlib.h,那麼gcc就會報出error:‘malloc’ was not declared in this scope。
其實這兩個函式用起來倒不是很難,也就是malloc()之後覺得用夠了就甩了它把它給free()了,舉個簡單例子:
// Code...
char *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == Ptr)
{
exit (1);
}gets(Ptr);
// code...
free(Ptr);
Ptr = NULL;
// code...
就是這樣!當然,具體情況要具體分析以及具體解決。比如說,你定義了一個指標,在一個函式裡申請了一塊記憶體然後通過函式返回傳遞給這個指標,那麼也許釋放這塊記憶體這項工作就應該留給其他函數了。
3、malloc函式與new函式區別
new返回指定型別的指標,並且可以自動計算所需要的大小。
int *p;
p = new int; //返回型別為int *型別,分配的大小為sizeof(int)
p = new int[100]; //返回型別為int *型別,分配的大小為sizeof(int) * 100
而malloc則必須由我們計算位元組數,並且在返回的時候強轉成實際指定型別的指標。
int *p;
p = (int *)malloc(sizeof(int));
.......
free(p);
- malloc的返回是void *,如果我們寫成了: p = malloc(sizeof(int)),間接的說明了(將void *轉化給了int *,這不合理);
- malloc的實參是sizeof(int),用於指明一個整形資料需要的大小,如果我們寫成:p = (int *)malloc(1),那麼可以看出:只是申請了一個位元組的空間,如果向裡面存放了一個整數的話,將會佔用額外的3個位元組,可能會改變原有記憶體空間中的資料;
- malloc只管分配記憶體,並不能對其進行初始化,所以得到的一片新記憶體中,其值將是隨機的。一般意義上:我們習慣性的將其初始化為NULL。當然,也可以用memset函式的。
簡單的說:malloc 函式其實就是在記憶體中:找一片指定大小的空間,然後將這個空間的首地址給一個指標變數,這裡的指標變數可以是一個單獨的指標,也可以是一個數組的首地址, 這要看malloc函式中引數size的具體內容。我們這裡malloc分配的記憶體空間在邏輯上是連續的,而在物理上可以不連續。我們作為程式設計師,關注的 是邏輯上的連續,其它的,作業系統會幫著我們處理的。
4、其他說明
關於該函式的原型,在以前malloc返回的是char型指標,新的ANSIC標準規定,該函式返回為void型指標,因此必要時要進行型別轉換。
如果分配成功則返回指向被分配記憶體的指標(此儲存區中的初始值不確定),否則返回空指標NULL。當記憶體不再使用時,應使用free()函式將記憶體塊釋放。函式返回的指標一定要適當對齊,使其可以用於任何資料物件。
5、malloc工作機制
malloc函式的實質體現在,它有一個將可用的記憶體塊連線為一個長長的列表的所謂空閒連結串列。呼叫malloc函式時,它沿連線表尋找一個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話)返回到連線表上。
呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片段,如果這時使用者申請一個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊。如果無法獲得符合要求的記憶體塊,malloc函式會返回NULL指標,因此在呼叫malloc動態申請記憶體塊時,一定要進行返回值的判斷。Linux Libc6採用的機制是在free的時候試圖整合相鄰的碎片,使其合併成為一個較大的free空間。
參考資料
[1]https://blog.csdn.net/chf_1/article/details/78688557
[2]https://www.cnblogs.com/Commence/p/5785912.html, 這篇寫的很詳細
[3]https://www.cnblogs.com/shiweihappy/p/4246372.html