前言
本期分為三篇介紹動態(tài)內(nèi)存管理相關(guān)內(nèi)容,關(guān)注博主了解更多
博主博客鏈接:https://blog.csdn.net/m0_74014525
本期介紹動態(tài)內(nèi)存函數(shù),函數(shù)如何使用、函數(shù)格式、在使用在所需要的注意點及C/C++程序的內(nèi)存開辟區(qū)域
系列文章
第一篇:C語言 — 動態(tài)內(nèi)存管理(動態(tài)內(nèi)存函數(shù))
第二篇:C語言 — 常見的動態(tài)內(nèi)存錯誤
第三篇:C語言 — 柔性數(shù)組
一、動態(tài)內(nèi)存分配是什么
動態(tài)內(nèi)存分配是指在程序運行期間由程序自己向操作系統(tǒng)請求分配一定大小的內(nèi)存空間,以存儲程序運行時所需的數(shù)據(jù)。 由于動態(tài)分配的內(nèi)存空間在程序運行期間是可變的,所以它比靜態(tài)分配更加靈活。
動態(tài)內(nèi)存分配帶來的好處是可以根據(jù)實際需要動態(tài)調(diào)整內(nèi)存大小,從而避免浪費內(nèi)存。 但是,如果程序員不小心管理動態(tài)分配的內(nèi)存,就可能會導(dǎo)致內(nèi)存泄漏或者內(nèi)存溢出等問題,嚴(yán)重影響程序的性能和穩(wěn)定性。因此,使用動態(tài)內(nèi)存分配時需要注意內(nèi)存的釋放和管理。
常見的動態(tài)內(nèi)存分配函數(shù)有 malloc
、calloc
、realloc
等。其中 malloc 分配指定大小的內(nèi)存塊,calloc 分配并初始化一定數(shù)量的內(nèi)存塊,realloc 可以重新調(diào)整已分配的內(nèi)存塊的大小。
二、為什么存在動態(tài)內(nèi)存分配
我們已經(jīng)掌握的內(nèi)存開辟方式有:
int val = 20;//在棧空間上開辟四個字節(jié)
char arr[10] = {0};//在??臻g上開辟10個字節(jié)的連續(xù)空間
但是上述的開辟空間的方式有兩個特點:
- 空間開辟大小是固定的。
- 數(shù)組在申明的時候,必須指定數(shù)組的長度,它所需要的內(nèi)存在編譯時分配。
但是對于空間的需求,不僅僅是上述的情況。
有時候我們需要的空間大小在程序運行的時候才能知道,
那數(shù)組的編譯時開辟空間的方式就不能滿足了。
這時候就只能試試動態(tài)存開辟了。
三、動態(tài)內(nèi)存函數(shù)的介紹
1. malloc
malloc
函數(shù)在C語言中用于在程序運行時向內(nèi)存申請一塊指定大小的內(nèi)存空間。
函數(shù)格式:
void* malloc (size_t size);
其中,size_t是一個無符號整數(shù)類型,用于表示申請內(nèi)存的字節(jié)數(shù)。malloc函數(shù)返回一個void指針,指向分配的內(nèi)存空間的起始地址。如果分配失敗,malloc函數(shù)返回空指針NULL。
函數(shù)特點:
- 如果開辟成功,則返回一個指向開辟好空間的指針。
- 如果開辟失敗,則返回一個NULL指針,因此malloc的返回值一定要做檢查。
- 返回值的類型是 void* ,所以malloc函數(shù)并不知道開辟空間的類型,具體在使用的時候使用者自己來決定。
- 如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器。
使用malloc函數(shù)申請內(nèi)存時,需要注意以下幾點:
1. | 申請的內(nèi)存大小應(yīng)該是變量或數(shù)據(jù)類型的字節(jié)數(shù)乘以需要存儲或操作的元素個數(shù),以保證申請到足夠的內(nèi)存空間。 |
2. | 申請到的內(nèi)存空間必須使用free函數(shù)進(jìn)行釋放,否則會導(dǎo)致內(nèi)存泄露。 |
3. | 申請到的內(nèi)存空間不會被自動初始化,即其中的數(shù)據(jù)是隨機(jī)的,需要手動進(jìn)行初始化。 |
舉例演示:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p;
p = (int*)malloc(10*sizeof(int)); //申請10個int類型數(shù)據(jù)的內(nèi)存空間
if (p == NULL) { //判斷申請是否成功
printf("Memory allocation failed.");
exit(1);
}
for (int i = 0; i < 10; i++) { //手動初始化數(shù)據(jù)
*(p+i) = i;
}
for (int i = 0; i < 10; i++) { //輸出數(shù)據(jù)
printf("%d\t", *(p+i));
}
free(p); //釋放內(nèi)存空間
p=NULL; //將指針置為空
return 0;
}
2. free
free
函數(shù)是 C 語言中用來釋放動態(tài)分配的內(nèi)存的函數(shù)
函數(shù)格式:
void free (void* ptr);
其中,ptr 是之前調(diào)用 malloc、calloc 或 realloc函數(shù)返回的指針。調(diào)用 free 函數(shù)后,指針?biāo)赶虻膬?nèi)存將會被操作系統(tǒng)回收,可以再次被分配給其他程序使用。
函數(shù)特點:
- 如果參數(shù) ptr 指向的空間不是動態(tài)開辟的,那free函數(shù)的行為是未定義的。
- 如果參數(shù) ptr 是NULL指針,則函數(shù)什么事都不做。
使用 free 函數(shù)的時候需要注意以下幾點:
1. | 只能釋放動態(tài)分配的內(nèi)存,不能釋放?;蛉肿兞恐械膬?nèi)存。 |
2. | 如果多次釋放同一個指針,會導(dǎo)致程序異常。 |
3. | 如果指針為空指針(NULL),則不會進(jìn)行任何操作。 |
3. calloc
calloc
函數(shù)是C語言中的一個內(nèi)存分配函數(shù),用于在內(nèi)存中分配指定大小的連續(xù)空間,并將其中的每個字節(jié)都初始化為0。
函數(shù)格式:
void* calloc (size_t num, size_t size);
其中,num表示要分配的元素數(shù)量,size表示每個元素的大小。函數(shù)返回一個指向新分配內(nèi)存的指針,如果分配失敗則返回NULL。
函數(shù)特點:
- 與函數(shù) malloc 的區(qū)別只在于 calloc 會在返回地址之前把申請的空間的每個字節(jié)初始化為全0。
- 與malloc函數(shù)不同,calloc函數(shù)在分配內(nèi)存時會自動清空分配的內(nèi)存空間,所以一般用于需要初始化內(nèi)存的情況。但它的缺點是比malloc函數(shù)慢,因為它需要在分配內(nèi)存時進(jìn)行清空操作。
使用calloc函數(shù)申請內(nèi)存時,需要注意以下幾點:
1. | 申請的內(nèi)存大小應(yīng)該是變量或數(shù)據(jù)類型的字節(jié)數(shù)乘以需要存儲或操作的元素個數(shù),以保證申請到足夠的內(nèi)存空間。 |
2. | 申請到的內(nèi)存空間必須使用free函數(shù)進(jìn)行釋放,否則會導(dǎo)致內(nèi)存泄露。 |
3. | 申請到的內(nèi)存空間不會被自動初始化,即其中的數(shù)據(jù)是隨機(jī)的,需要手動進(jìn)行初始化。 |
4. | 區(qū)別于malloc,calloc 會在返回地址之前把申請的空間的每個字節(jié)初始化為全0。 |
舉例演示:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));
if (NULL != p)
{
//使用空間
}
free(p);
p = NULL;
return 0;
}
如何對申請的內(nèi)存空間的內(nèi)容要求初始化,那么可以很方便的使用calloc函數(shù)來完成任務(wù)
4. realloc
realloc
函數(shù)是C語言中的一個庫函數(shù),用于重新分配動態(tài)分配的內(nèi)存空間。
1.用于調(diào)整現(xiàn)有的內(nèi)存塊大小、
2.分配新的內(nèi)存塊
3.用于釋放現(xiàn)有的內(nèi)存塊,當(dāng)傳遞給它一個空指針時。
函數(shù)格式:
void* realloc(void* ptr, size_t size);
ptr表示指向已經(jīng)動態(tài)分配的內(nèi)存塊的指針。
size表示需要重新分配的內(nèi)存塊的新尺寸。
返回值:如果分配失敗,則返回NULL指針;否則返回一個新的指針,指向重新分配后的內(nèi)存塊。
函數(shù)特點:
使用realloc函數(shù)申請內(nèi)存時,需要注意以下幾點:
1. | 如果新的尺寸大于舊的尺寸,realloc函數(shù)將在原來的內(nèi)存塊后面分配額外的內(nèi)存,使其達(dá)到新的尺寸。 |
2. | 如果新的尺寸小于舊的尺寸,realloc函數(shù)將會釋放一部分內(nèi)存,使其達(dá)到新的尺寸。 |
3. | 如果ptr是空指針,則等同于調(diào)用malloc函數(shù)。如果size是0,等同于調(diào)用free函數(shù)。 |
realloc在調(diào)整內(nèi)存空間的是存在兩種情況:
- 情況1:原有空間之后有足夠大的空間
- 情況2:原有空間之后沒有足夠大的空間
情況1:
當(dāng)是情況1 的時候,要擴(kuò)展內(nèi)存就直接原有內(nèi)存之后直接追加空間,原來空間的數(shù)據(jù)不發(fā)生變化。
情況2:
當(dāng)是情況2 的時候,原有空間之后沒有足夠多的空間時,
擴(kuò)展的方法是:在堆空間上另找一個合適大小的連續(xù)空間來使用。這樣函數(shù)返回的是一個新的內(nèi)存地址。
由于上述的兩種情況,realloc函數(shù)的使用就要注意一些。
四、C/C++程序的內(nèi)存開辟
1. 內(nèi)存分配區(qū)域
C/C++程序內(nèi)存分配的幾個區(qū)域:
棧區(qū)(stack) | 在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元自動被釋放。棧內(nèi)存分配運算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。 棧區(qū)主要存放運行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回數(shù)據(jù)、返回地址等。 |
堆區(qū)(heap) | 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時可能由OS回收 。分配方式類似于鏈表。 |
數(shù)據(jù)段 (靜態(tài)區(qū))(static) | 存放全局變量、靜態(tài)數(shù)據(jù)。程序結(jié)束后由系統(tǒng)釋放。 |
代碼段 | 存放函數(shù)體(類成員函數(shù)和全局函數(shù))的二進(jìn)制代碼。 |
總結(jié)
本期博客的重要點概況:malloc
函數(shù):用于動態(tài)內(nèi)存的開辟calloc
函數(shù):也是用于動態(tài)內(nèi)存開辟,區(qū)別于malloc,calloc函數(shù)會將每一個字節(jié)初始化為0realloc
函數(shù):用于擴(kuò)展內(nèi)存空間,需要注意增加內(nèi)存的返回,分為情況1和2free
函數(shù):用于釋放動態(tài)內(nèi)存空間文章來源:http://www.zghlxwxcb.cn/news/detail-631011.html
如這篇博客對大家有幫助的話,希望 三連 支持一下 ?。。?如果有錯誤感謝大佬的斧正 如有 其他見解發(fā)到評論區(qū),一起學(xué)習(xí) 一起進(jìn)步。
文章來源地址http://www.zghlxwxcb.cn/news/detail-631011.html
到了這里,關(guān)于C語言 — 動態(tài)內(nèi)存管理(動態(tài)內(nèi)存函數(shù))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!