原型:extern void *malloc(unsigned int num_bytes);
頭文件:在TC2.0中可以用malloc.h或 alloc.h (注意:alloc.h 與 malloc.h 的內容是完全一致的),而在Visual C++6.0中可以用malloc.h或者
stdlib.h。
功能:分配長度為num_bytes字節的內存塊
返回值:如果分配成功則返回指向被分配內存的
指針(此存儲區中的初始值不確定),否則返回空指針NULL。當內存不再使用時,應使用
free()函數將內存塊釋放。函數返回的指針一定要適當對齊,使其可以用於任何
數據對象。
說明:關於該函數的原型,在舊的版本中malloc返回的是char型指針,新的ANSIC標准規定,該函數返回為void型指針,因此必要時要進行類型轉換。
名稱解釋:malloc的全稱是memory allocation,中文叫
動態內存分配,當無法知道內存具體位置的時候,想要綁定真正的內存空間,就需要用到動態的分配內存。
相關函數:
calloc、
realloc、free、_alloca
void *malloc(size_t size);
備注:void* 表示未確定類型的
指針,void *可以指向任何類型的數據,更明確的說是指申請內存空間時還不知道用戶是用這段空間來存儲什么類型的數據(比如是char還是int或者...)
從函數聲明上可以看出。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)*128);//分配128個(可根據實際需要替換該數值)整型存儲單元,並將這128個連續的整型存儲單元的首地址存儲到
指針變量p中
double *pd=(double *) malloc (sizeof(double)*12);//分配12個double型存儲單元,並將首地址存儲到指針變量pd中
第一、malloc 函數返回的是 void * 類型。對於C++,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,報錯:“不能將 void* 賦值給 int * 類型
變量”。所以必須通過 (int *) 來將
強制轉換。而對於C,沒有這個要求,但為了使C程序更方便的移植到C++中來,建議養成強制轉換的習慣。
第二、函數的
實參為 sizeof(int) ,用於指明一個
整型數據需要的大小。如果你寫成:
int* p = (int *) malloc (1);
代碼也能通過編譯,但事實上只分配了1個字節大小的內存空間,當你往里頭存入一個整數,就會有3個字節無家可歸,而直接“住進鄰居家”!造成的結果是后面的內存中原有數據內容被改寫。
在Linux中可以有這樣:malloc(0),這是因為Linux中malloc有一個下限值16Bytes,注意malloc(-1)是禁止的;
但是在某些系統中是不允許malloc(0)的。在規范的程序中我們有必要按照這樣的格式去使用malloc及
free:
type *p;
if (NULL == (p = (type *)malloc(sizeof (type)))) /*請使用if來判斷,這是有必要的*/
{
perror("error...");
exit(1);
}
... /*其它代碼*/
free(p);
p = NULL; /*請加上這句*/
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函數時,它沿
連接表尋找一個大到足以滿足用戶請求所需要的內存塊。然后,將該內存塊一分為二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(如果有的話)返回到連接表上。調用
free函數時,它將用戶釋放的內存塊連接到空閑鏈上。到最后,空閑鏈會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那么空閑鏈上可能沒有可以滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閑鏈上翻箱倒櫃地檢查各內存片段,對它們進行整理,將相鄰的小空閑塊合並成較大的內存塊。如果無法獲得符合要求的內存塊,malloc函數會返回NULL
指針,因此在調用malloc動態申請內存塊時,一定要進行返回值的判斷。
Linux Libc6采用的機制是在free的時候試圖整合相鄰的碎片,使其合並稱為一個較大的free空間。
正常片段:
typedef struct data_type{
int age;
char name[20];
} data;
data *bob;
bob = (data *) malloc( sizeof(data) );
if( bob != NULL ) {
bob->age = 22;
strcpy( bob->name, "Robert" );
printf( "%s is %d years old\n", bob->name, bob->age );
}else{
printf("malloc error!\n");
exit(1);
}
free( bob );
內存泄漏實例:
#include <stdio.h>
#include <malloc.h>
#define MAX 100000000
int main(void) {
int *a[MAX];
int i;
for( i=0; i<MAX; i++ ) {
a[i] = (int *)malloc( MAX );
}
return 0;
}