定義
原型
extern void *malloc(unsigned int num_bytes);
頭文件
#include
功能
分配長度為num_bytes字節的内存塊
返回值
如果分配成功則返回指向被分配内存的指針(此存儲區中的初始值不确定),否則返回空指針NULL。當内存不再使用時,應使用free()函數将内存塊釋放。函數返回的指針一定要适當對齊,使其可以用于任何數據對象。
說明
關于該函數的原型,在以前malloc返回的是char型指針,新的ANSIC标準規定,該函數返回為void型指針,因此必要時要進行類型轉換。
名稱解釋
malloc的全稱是memory allocation,中文叫動态内存分配,當無法知道内存具體位置的時候,想要綁定真正的内存空間,就需要用到動态的分配内存。
相關函數
calloc、realloc、free、_alloca
函數聲明
全名
void *malloc(size_t size);
備注
void* 表示未确定類型的指針,void *可以指向任何類型的數據,更明确的說是指申請内存空間時還不知道用戶是用這段空間來存儲什麼類型的數據(比如是char還是int或者...)
與new的區别
從本質上來說,malloc(Linux上具體實現可以參考man malloc,glibc通過brk()&mmap()實現)是libc裡面實現的一個函數,如果在source code中沒有直接或者間接include過stdlib.h,那麼gcc就會報出error:‘malloc’ was not declared in this scope。
如果生成了目标文件(假定動态鍊接malloc),如果運行平台上沒有libc(Linux平台,手動指定LD_LIBRARY_PATH到一個空目錄即可),或者libc中沒有malloc函數,那麼會在運行時(Run-time)出錯。new則不然,是c++的關鍵字,它本身不是函數。new不依賴于頭文件,c++編譯器就可以把new編譯成目标代碼(g++4.6.3會向目标中插入_Znwm這個函數,另外,編譯器還會根據參數的類型,插入相應的構造函數)。
在使用上,malloc 和 new 至少有兩個不同: new 返回指定類型的指針,并且可以自動計算所需要大小。比如:
或:
而 malloc 則必須要由我們計算字節數,并且在返回後強行轉換為實際類型的指針。
第一、malloc 函數返回的是 void * 類型。對于C++,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,報錯:“不能将 void* 賦值給 int * 類型變量”。所以必須通過 (int *) 來将強制轉換。而對于C,沒有這個要求,但為了使C程序更方便的移植到C++中來,建議養成強制轉換的習慣。
第二、函數的實參為 sizeof(int) ,用于指明一個整型數據需要的大小。
在Linux中可以有這樣:malloc(0),這是因為Linux中malloc有一個下限值16Bytes,注意malloc(-1)是禁止的;
但是在某些系統中是不允許malloc(0)的。在規範的程序中我們有必要按照這樣的格式去使用malloc及free:
malloc 也可以達到 new [] 的效果,申請出一段連續的内存,方法無非是指定你所需要内存大小。
比如想分配100個int類型的空間:
另外有一點不能直接看出的區别是,malloc 隻管分配内存,并不能對所得的内存進行初始化,所以得到的一片新内存中,其值将是随機的。
除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指針,在其它操作上保持一緻。
對其做一個特例補充
此時得到的是Got a valid pointer。把0賦給malloc能得到一個合法的指針。
工作機制
malloc函數的實質體現在,它有一個将可用的内存塊連接為一個長長的列表的所謂空閑鍊表。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的内存塊。然後,将該内存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。
接下來,将分配給用戶的那塊内存傳給用戶,并将剩下的那塊(如果有的話)返回到連接表上。調用free函數時,它将用戶釋放的内存塊連接到空閑鍊上。到最後,空閑鍊會被切成很多的小内存片段,如果這時用戶申請一個大的内存片段,那麼空閑鍊上可能沒有可以滿足用戶要求的片段了。
于是,malloc函數請求延時,并開始在空閑鍊上翻箱倒櫃地檢查各内存片段,對它們進行整理,将相鄰的小空閑塊合并成較大的内存塊。如果無法獲得符合要求的内存塊,malloc函數會返回NULL指針,因此在調用malloc動态申請内存塊時,一定要進行返回值的判斷。
Linux Libc6采用的機制是在free的時候試圖整合相鄰的碎片,使其合并成為一個較大的free空間。