最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于C語(yǔ)言動(dòng)態(tài)內(nèi)存管理介紹

 更新時(shí)間:2022年01月27日 15:28:19   作者:invictusQAQ  
大家好,本篇文章主要講的是關(guān)于C語(yǔ)言動(dòng)態(tài)內(nèi)存管理介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下

1.為什么需要?jiǎng)討B(tài)內(nèi)存分配

關(guān)于這個(gè)問(wèn)題,我們先看看我們之前是如何開(kāi)辟內(nèi)存的。

int val = 20;//在棧空間上開(kāi)辟四個(gè)字節(jié)
char arr[10] = {0};//在??臻g上開(kāi)辟10個(gè)字節(jié)的連續(xù)空間

但可以發(fā)現(xiàn)的一個(gè)問(wèn)題是,無(wú)論我們?cè)鯓娱_(kāi)辟內(nèi)存空間,他的大小都在開(kāi)辟前就已經(jīng)被指定,而顯然在實(shí)際應(yīng)用中并不是所有情況我們都能在程序編譯前就知道他需要多大的內(nèi)存空間。或許你想說(shuō)那有備無(wú)患開(kāi)大點(diǎn)不久好了?但這樣所造成的空間浪費(fèi)并不是我們所希望看到的結(jié)果。于是我們就只能試試動(dòng)態(tài)內(nèi)存分配了。

2.有關(guān)動(dòng)態(tài)內(nèi)存函數(shù)介紹

2.1 malloc和free

c語(yǔ)言已經(jīng)為我們提供了一個(gè)動(dòng)態(tài)內(nèi)存開(kāi)辟的函數(shù)malloc

void* malloc (size_t size);

1.這個(gè)函數(shù)向內(nèi)存申請(qǐng)一塊連續(xù)可用的空間,并返回指向這塊空間的指針。

2.如果開(kāi)辟成功,則返回一個(gè)指向開(kāi)辟好空間的指針。

3.如果開(kāi)辟失敗,則返回一個(gè)NULL指針,因此malloc的返回值一定要做檢查。

4.返回值的類(lèi)型是 void* ,所以malloc函數(shù)并不知道開(kāi)辟空間的類(lèi)型,具體在使用的時(shí)候使用者自 己來(lái)決定。

5.如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器。

當(dāng)然有分配就會(huì)有釋放,c語(yǔ)言也為我們提供了另一個(gè)函數(shù)free,專(zhuān)門(mén)用來(lái)做動(dòng)態(tài)內(nèi)存的釋放以及回收,函數(shù)原型如下。

void free (void* ptr);

1.free函數(shù)用來(lái)釋放動(dòng)態(tài)開(kāi)辟的內(nèi)存。

2.如果參數(shù) ptr 指向的空間不是動(dòng)態(tài)開(kāi)辟的,那free函數(shù)的行為是未定義的。

3.如果參數(shù) ptr 是NULL指針,則函數(shù)什么事都不做。

我們看到下面的一個(gè)例子

#include <stdio.h>
int main()
{
	int* ptr = NULL;
	ptr = (int*)malloc(num * sizeof(int));
	if (NULL != ptr)//判斷ptr指針是否為空
	{
		int i = 0;
		for (i = 0; i < num; i++)
		{
			*(ptr + i) = 0;
		}
	}
	free(ptr);//釋放ptr所指向的動(dòng)態(tài)內(nèi)存
	ptr = NULL;
	return 0;
}

相信這串代碼大家在有注釋的情況下都能夠看懂。但是有細(xì)心的讀者可能會(huì)發(fā)現(xiàn)free(ptr)之后又令ptr=NULL,這是為什么呢?其實(shí)在一塊內(nèi)存空間被釋放后,該指針仍指向被釋放掉的內(nèi)存地址,而此時(shí)的ptr便成了野指針,一旦后續(xù)不小心被程序調(diào)用就會(huì)導(dǎo)致程序崩潰,所以在指針釋放后要將其置為NULL防止這種情況的發(fā)生。

2.2 calloc函數(shù)

calloc函數(shù)類(lèi)似與malloc,同樣用于動(dòng)態(tài)內(nèi)存分配,函數(shù)原型如下。

void* calloc (size_t num, size_t size);

函數(shù)的功能是為 num個(gè)大小為size的元素開(kāi)辟一塊空間,并且把空間的每個(gè)字節(jié)初始化為0。

與函數(shù)malloc的區(qū)別只在于calloc會(huì)在返回地址之前把申請(qǐng)的空間的每個(gè)字節(jié)初始化為全0。

2.3 realloc函數(shù)

有時(shí)會(huì)我們發(fā)現(xiàn)過(guò)去申請(qǐng)的空間太小了,有時(shí)候我們又會(huì)覺(jué)得申請(qǐng)的空間過(guò)大了,那為了合理的時(shí) 候內(nèi)存,我們一定會(huì)對(duì)內(nèi)存的大小做靈活的調(diào)整。那 realloc 函數(shù)就可以做到對(duì)動(dòng)態(tài)開(kāi)辟內(nèi)存大 小的調(diào)整。函數(shù)原型如下。

void* realloc (void* ptr, size_t size);

ptr 是要調(diào)整的內(nèi)存地址

size 調(diào)整之后新大小

返回值為調(diào)整之后的內(nèi)存起始位置。

這個(gè)函數(shù)調(diào)整原內(nèi)存空間大小的基礎(chǔ)上,還會(huì)將原來(lái)內(nèi)存中的數(shù)據(jù)移動(dòng)到新的空間。

需要注意的是:

realloc在調(diào)整內(nèi)存空間時(shí)存在兩種情況

情況1:原有空間之后有足夠大的空間

情況2:原有空間之后沒(méi)有足夠大的空間

參見(jiàn)下圖示意

 情況1

當(dāng)是情況1的時(shí)候,要擴(kuò)展內(nèi)存就直接原有內(nèi)存之后直接追加空間,原來(lái)空間的數(shù)據(jù)不發(fā)生變化。

情況2

當(dāng)是情況2 的時(shí)候,原有空間之后沒(méi)有足夠多的空間時(shí),擴(kuò)展的方法是:在堆空間上另找一個(gè)合適大小 的連續(xù)空間來(lái)使用。這樣函數(shù)返回的是一個(gè)新的內(nèi)存地址。

針對(duì)情況二,若realloc成功,指向原內(nèi)存地址的指針就成了懸掛指針,即指針指向了一塊沒(méi)有分配給用戶(hù)使用的內(nèi)存,如果再使用該指針進(jìn)行操作就可能發(fā)生意想不到的情況,因此要格外注意這種情況。

#include <stdio.h>
int main()
{
	int* ptr = (int*)malloc(100);//動(dòng)態(tài)分配
	int* p = NULL;
	p = (int*)realloc(ptr, 1000);//重分配
	if (p != NULL)//判斷是否成功
	{
		ptr = p;//防止懸掛指針出現(xiàn)
	}
	//業(yè)務(wù)處理
	free(ptr);
    ptr=NULL;//釋放后置空防止野指針
	return 0;
}

注意動(dòng)態(tài)內(nèi)存分配時(shí)應(yīng)當(dāng)像上述代碼一樣盡量規(guī)范。

3. 常見(jiàn)的動(dòng)態(tài)內(nèi)存錯(cuò)誤

3.1 對(duì)NULL指針進(jìn)行解引用操作

這個(gè)點(diǎn)就不再過(guò)多敘述,大家記住即可,對(duì)空指針進(jìn)行解引用操作可能會(huì)引發(fā)各種奇怪的問(wèn)題。

3.2 對(duì)動(dòng)態(tài)開(kāi)辟空間的越界訪(fǎng)問(wèn)

同數(shù)組類(lèi)似,即使是動(dòng)態(tài)開(kāi)辟的空間也不能越界訪(fǎng)問(wèn)。

3.3 對(duì)非動(dòng)態(tài)開(kāi)辟內(nèi)存使用free釋放

切記只有動(dòng)態(tài)開(kāi)辟的內(nèi)存才能使用free。

3.4 使用free釋放一塊動(dòng)態(tài)開(kāi)辟內(nèi)存的一部分

參見(jiàn)下面代碼

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向動(dòng)態(tài)內(nèi)存的起始位置
}

雖然有些小伙伴可能想既然free函數(shù)是根據(jù)指針來(lái)釋放內(nèi)存的,那我能不能通過(guò)對(duì)指針進(jìn)行操作去部分釋放動(dòng)態(tài)分配的內(nèi)存呢?然而夢(mèng)想很美好,現(xiàn)實(shí)很骨感。如果強(qiáng)行這樣做的話(huà)只可能會(huì)造成·更多不可預(yù)估的結(jié)果。

3.5 對(duì)同一塊動(dòng)態(tài)內(nèi)存多次釋放

這個(gè)錯(cuò)誤應(yīng)該大家目前應(yīng)該不太常犯,但是一旦后面代碼量大了之后就很有可能忘記是否已經(jīng)釋放過(guò)內(nèi)存從而導(dǎo)致重復(fù)釋放而bug。

3.6 動(dòng)態(tài)開(kāi)辟內(nèi)存忘記釋放(內(nèi)存泄漏)

void test()
{
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
}
int main()
{
 test();
 while(1);
}

看到這個(gè)標(biāo)題再看這串代碼,大家應(yīng)該都很容易能夠知道上面的代碼忘記釋放內(nèi)存了從而導(dǎo)致內(nèi)存泄漏,但實(shí)際日常我們非常容易忘記開(kāi)辟內(nèi)存后free。

忘記釋放不再使用的動(dòng)態(tài)開(kāi)辟的空間會(huì)造成內(nèi)存泄漏。

切記:

動(dòng)態(tài)開(kāi)辟的空間一定要釋放,并且正確釋放 。

總結(jié)

到此這篇關(guān)于關(guān)于C語(yǔ)言動(dòng)態(tài)內(nèi)存管理介紹的文章就介紹到這了,更多相關(guān)C語(yǔ)言動(dòng)態(tài)內(nèi)存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

黄大仙区| 循化| 无棣县| 富裕县| 浮山县| 盱眙县| 昌乐县| 金溪县| 南皮县| 长子县| 灵石县| 资阳市| 盐源县| 三都| 驻马店市| 横峰县| 新昌县| 交城县| 海南省| 石家庄市| 龙州县| 神池县| 莱阳市| 灌云县| 蓬溪县| 义乌市| 方正县| 莱州市| 渝北区| 巴彦淖尔市| 闽侯县| 平罗县| 宁晋县| 前郭尔| 潍坊市| 石屏县| 固安县| 习水县| 托克逊县| 东台市| 新民市|