天天看點

c語言釋放記憶體函數,【C語言】記憶體配置設定函數malloc/ calloc/ realloc及記憶體釋放free

前言:

記憶體區域劃分與配置設定:

1、棧區(stack)——程式運作時由編譯器自動配置設定,存放函數的參數值,局部變量的值等,程式結束時由編譯器自動釋放。

2、堆區(heap) —— 在記憶體開辟另一塊存儲區域。一般由程式員配置設定釋放, 若程式員不釋放,程式結束時可能由OS回收 。用malloc, calloc, realloc等配置設定記憶體的函數配置設定得到的就是在堆上。

3、全局區(靜态區)(static)——編譯器編譯時即配置設定記憶體。全局變量和靜态變量的存儲是放在一塊的。對于C語言初始化的全局變量和靜态變量在一塊區域, 未初始化的全局變量和未初始化的靜态變量在相鄰的另一塊區域。而C++則沒有這個差別 - 程式結束後由系統釋放

4、文字常量區 ——常量字元串就是放在這裡的, 程式結束後由系統釋放。

5、程式代碼區——存放函數體的二進制代碼。

初識記憶體配置設定函數malloc/ calloc/ realloc及記憶體釋放free

從前言中我們知道,如果要想申請一段動态記憶體需要常見的堆上記憶體管理函數malloc(), calloc(), recalloc(), free(),而堆上的記憶體空間不會自動釋放,直到調用free()函數,才會釋放堆上的存儲空間。

接下來我們一起來看一下這些函數具體實作及功能差別

1、malloc()

頭檔案:stdlib.h

聲明:void *malloc(size_t size);

含義:在堆上,配置設定size個位元組,并傳回void指針類型。

傳回值:配置設定記憶體成功,傳回配置設定的堆上存儲空間的首位址;否則,傳回NULL

例如:給一個長度為4的字元數組申請一個動态記憶體

char *p = (char *)malloc(4*sizeof(char));

2、calloc()

頭檔案:stdlib.h

聲明:void *calloc(size_t nobj, size_t size);

含義:在堆上,配置設定nobj*size個位元組,并初始化為0,傳回void* 類型

傳回值:同malloc() 函數

例如:給一個長度為4的字元數組申請一個動态記憶體,并初識化為0.

char *p = (char *)calloc(4,sizeof(char));

=char *p = (char *)malloc(4*sizeof(char));

for(int i=0;i<4;i++)

{

p[i]=0;

}

3、recalloc()

頭檔案:stdlib.h

聲明:void *realloc(void *p, size_t size);//新的大小一定要大于原來的大小不然的話會導緻資料丢失!

含義:重新配置設定堆上的void指針p所指的空間為個位元組,同時會複制原有内容到新配置設定的堆上存儲空間。注意,若原來的void指針p在堆上的空間不大于n個位元組,則保持不變。

傳回值:同malloc() 函數

例如:給一個長度為4的字元數組動态記憶體擴容為一個長度為8的字元數組

p=(char*)realloc(p,8*sizeof(char))

=char *p = (char *)malloc(4*sizeof(char));

for(int i=0;i<4;i++)

{

p[i]=i;

}

char *q = (char *)malloc(8*sizeof(char));

for(int i=0;i<4;i++)

{

q[i]=p[i];

}

free(p);

p=q;

q=NULL;

(過程大概如右:重新申請一段記憶體——>将原來的值移到新空間——>釋放原來記憶體——>更改位址)

4、free()

頭檔案:stdlib.h

聲明:void free(void *p);

含義:釋放void指針p所指的堆上的空間。

傳回值:無

對于free(p)這句語句,如果p 是NULL 指針,那麼free 對p無論操作多少次都不會出問題。如果p 不是NULL 指針,那麼free 對p連續操作兩次就會導緻程式運作錯誤。

free函數如何知道釋放的位置及大小?

答案:實際上在free釋放的時候會根據傳入的位址向前偏移一定位元組(頭), 從這些位元組中擷取具體的記憶體塊大小并釋放。

free 函數崩潰的原因:

1、越界(把尾資訊給破壞了)

2、修改指針的指向(free找不到頭資訊)

3、重複釋放同一段記憶體

4、釋放非動态建立的記憶體