malloc函式
malloc 向系統申請分配指定size個位元組的記憶體空間。返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可以強制轉換為任何其它型別的指標。
- 中文名
- 動態記憶體分配
- 外文名
- memory allocation
- 簡 稱
- malloc
- 原 型
- extern void *malloc
函式定義
編輯原型
1
|
extern void * malloc (unsigned int num_bytes); |
標頭檔案
1
2
|
#include <stdlib.h> #include <malloc.h> |
函式宣告
1
|
void * malloc ( size_t size); |
功能
分配長度為num_bytes位元組的記憶體塊
返回值
如果分配成功則返回指向被分配記憶體的指標(此儲存區中的初始值不確定),否則返回空指標NULL。當記憶體不再使用時,應使用free()函式將記憶體塊釋放。函式返回的指標一定要適當對齊,使其可以用於任何資料物件。
說明
名稱解釋
malloc的全稱是memory allocation,中文叫動態記憶體分配,當無法知道記憶體具體位置的時候,想要繫結真正的記憶體空間,就需要用到動態的分配記憶體。
相關函式
與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 返回指定型別的指標,並且可以自動計算所需要大小。比如:
1
2
3
|
int *p; p = new int ; //返回型別為int *型別(整數型指標),分配大小為sizeof(int); |
或:
1
2
3
|
int *parr; parr = new int [100]; //返回型別為int *型別(整數型指標),分配大小為sizeof(int) * 100; |
而 malloc 則必須要由我們計算位元組數,並且在返回後強行轉換為實際型別的指標。
1
2
3
4
5
6
7
|
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++中來,建議養成強制轉換的習慣。
在Linux中可以有這樣:malloc(0),這是因為Linux中malloc有一個下限值16Bytes,注意malloc(-1)是禁止的;但是在某些系統中是不允許malloc(0)的。
在規範的程式中我們有必要按照這樣的格式去使用malloc及free:
1
2
3
4
5
6
7
8
9
10
|
type *p; if (NULL == (p = (type*) malloc ( sizeof (type)))) /*請使用if來判斷,這是有必要的*/ { perror ( "error..." ); exit (1); } ... /*其它程式碼*/ free (p); p = NULL; /*請加上這句*/ |
malloc 也可以達到 new [] 的效果,申請出一段連續的記憶體,方法無非是指定你所需要記憶體大小。
比如想分配100個int型別的空間:
1
2
|
int *p = ( int *) malloc ( sizeof ( int ) * 100); //分配可以放得下100個整數的記憶體空間。 |
另外有一點不能直接看出的區別是,malloc 只管分配記憶體,並不能對所得的記憶體進行初始化,所以得到的一片新記憶體中,其值將是隨機的。
除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指標,在其它操作上保持一致。
對其做一個特例補充
1
2
3
4
5
|
char *ptr; if ((ptr = ( char *) malloc (0)) == NULL) puts ( "Gotanullpointer" ); else puts ( "Gotavalidpointer" ); |
此時得到的是Got a valid pointer。把0賦給malloc能得到一個合法的指標。
工作機制
編輯malloc函式的實質體現在,它有一個將可用的記憶體塊連線為一個長長的列表的所謂空閒連結串列。呼叫malloc函式時,它沿連線表尋找一個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話)返回到連線表上。呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片段,如果這時使用者申請一個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊。如果無法獲得符合要求的記憶體塊,malloc函式會返回NULL指標,因此在呼叫malloc動態申請記憶體塊時,一定要進行返回值的判斷。
Linux Libc6採用的機制是在free的時候試圖整合相鄰的碎片,使其合併成為一個較大的free空間。
程式示例
編輯正常程式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
typedef struct data_type{ int age; char name[20]; }data; data*bob=NULL; bob=(data*) malloc ( sizeof (data)); if (bob!=NULL) { bob->age=22; strcpy (bob->name, "Robert" ); printf ( "%sis%dyearsold\n" ,bob->name,bob->age); } else { printf ( "mallocerror!\n" ); exit (-1); } free (bob); bob=NULL; |
記憶體洩漏例項
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
例1: #include <stdio.h> #include <malloc.h> #define MAX 100000000 int main( void ) { int *a[MAX] = {NULL}; int i; for (i=0;i<MAX;i++) { a[i]=( int *) malloc (MAX); } return 0; } |
例2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include "stdio.h" #include "malloc.h"//malloc()函式被包含在malloc.h裡面 int main( void ) { char *a = NULL; //宣告一個指向a的char*型別的指標 a = ( char *) malloc (100* sizeof ( char )); //使用malloc分配記憶體的首地址,然後賦值給a if (!a) //如果malloc失敗,可以得到一些log { perror ( "malloc" ); return -1; } sprintf (a, "%s" , "HelloWorld\n" ); //"HelloWorld\n"寫入a指向的地址 printf ( "%s\n" ,a); //輸出使用者輸入的資料 free (a); //釋放掉使用的記憶體地址 return 0; //例2有無記憶體洩露? } 注:例1:對 malloc 申請之後沒有檢測返回值;例2:檢測 malloc 返回值條件有誤。 |
相關文章
- malloc函式詳解函式
- malloc,calloc,realloc等記憶體分配函式區別記憶體函式
- 【C/C++】記憶體分配函式:malloc,calloc,realloc,_allocaC++記憶體函式
- C語言malloc()函式:動態分配記憶體空間C語言函式記憶體
- [CareerCup] 13.9 Aligned Malloc and Free Function 寫一對申請和釋放記憶體函式Function記憶體函式
- MySQL函式大全(字串函式,數學函式,日期函式,系統級函式,聚合函式)MySql函式字串
- Oracle 函式大全(字串函式,數學函式,日期函式,邏輯運算函式,其他函式)Oracle函式字串
- 【函式式 Swift】函式式思想函式Swift
- python中id()函式、zip()函式、map()函式、lamda函式Python函式
- 【函式】Oracle函式系列(2)--數學函式及日期函式函式Oracle
- Python 擴充之特殊函式(lambda 函式,map 函式,filter 函式,reduce 函式)Python函式Filter
- CSAPP Malloc LabAPP
- 第7章 IF函式 COUNTIF函式 SUMIF函式函式
- 字元函式、數字函式和日期函式字元函式
- 【函式】Oracle EXTRACT()函式與to_char() 函式函式Oracle
- MySQL(四)日期函式 NULL函式 字串函式MySql函式Null字串
- 【函式】ORACLE函式大全函式Oracle
- (譯) 函式式 JS #2: 函式!函式JS
- 核函式 多項式核函式 高斯核函式(常用)函式
- 函式名/函式地址/函式指標函式指標
- 第 8 節:函式-匿名函式、遞迴函式函式遞迴
- lambda匿名函式sorted排序函式filter過濾函式map對映函式函式排序Filter
- js函式 函式自呼叫 返回函式的函式 (閉包)JS函式
- main函式的入口函式AI函式
- (函式)實現strstr函式函式
- 字串函式之Strtok()函式字串函式
- SQL函式之日期函式SQL函式
- Oracle聚合函式/分析函式Oracle函式
- fork函式與vfork函式函式
- 常用函式--時間函式函式
- ORACLE單行函式與多行函式之七:多行函式之分組函式示例Oracle函式
- 函式式JavaScript(4):函式柯里化函式JavaScript
- 箭頭函式、簡寫函式、普通函式的區別函式
- Oracle OCP(03):字元函式、數字函式和日期函式Oracle字元函式
- webgl內建函式--幾何函式與矩陣函式Web函式矩陣
- webgl內建函式--向量函式與紋理查詢函式Web函式
- Hive函式(內建函式+自定義標準函式UDF)Hive函式
- 深入理解 函式、匿名函式、自執行匿名函式函式