真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

動(dòng)態(tài)內(nèi)存分配/管理-創(chuàng)新互聯(lián)

目錄

成都創(chuàng)新互聯(lián)公司基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)綿陽(yáng)服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。

1、為什么要有動(dòng)態(tài)內(nèi)存分配

2、動(dòng)態(tài)內(nèi)存函數(shù)介紹

1、malloc

2、free

3、calloc

?編輯

4、realloc

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

4、動(dòng)態(tài)內(nèi)存開(kāi)辟相關(guān)好題

5、c/c++程序內(nèi)存開(kāi)辟示意圖


int a,? int arr[10]? 是固定地向內(nèi)存申請(qǐng)連續(xù)的一塊空間,但不能變長(zhǎng)或變短隨時(shí)調(diào)整。

在我們之前寫(xiě)的靜態(tài)版通訊錄中,我們創(chuàng)建了一個(gè)peopleinfo類型的數(shù)組date[100]用來(lái)存放100個(gè)人的個(gè)人信息,但是當(dāng)我們的人員信息較小時(shí),100個(gè)結(jié)構(gòu)體顯得有些浪費(fèi),而當(dāng)我們所需存放的信息超過(guò)100時(shí)又不夠用,隨之我們就得修改這個(gè)數(shù)字,但是學(xué)了動(dòng)態(tài)內(nèi)存管理之后,我們可以動(dòng)態(tài)地分配內(nèi)存空間變大或變小,從而有效利用空間。

1、為什么要有動(dòng)態(tài)內(nèi)存分配

int val = 20;//在棧空間上開(kāi)辟四個(gè)字節(jié)
char arr[10] = {0};//在??臻g上開(kāi)辟10個(gè)字節(jié)的連續(xù)空間
但是上述的開(kāi)辟空間的方式有兩個(gè)特點(diǎn):
1. 空間開(kāi)辟大小是固定的。
2. 數(shù)組在申明的時(shí)候,必須指定數(shù)組的長(zhǎng)度,它所需要的內(nèi)存在編譯時(shí)分配。
但是對(duì)于空間的需求,不僅僅是上述的情況。有時(shí)候我們需要的空間大小在程序運(yùn)行的時(shí)候才能知道,
那數(shù)組的編譯時(shí)開(kāi)辟空間的方式就不能滿足了。
這時(shí)候就只能使用動(dòng)態(tài)內(nèi)存開(kāi)辟了。

2、動(dòng)態(tài)內(nèi)存函數(shù)介紹 1、malloc

#include

這個(gè)函數(shù)向內(nèi)存申請(qǐng)一塊連續(xù)可用的空間,并返回指向這塊空間的指針。
如果開(kāi)辟成功,則返回一個(gè)指向開(kāi)辟好空間的指針。
如果開(kāi)辟失敗,則返回一個(gè)NULL指針,因此malloc的返回值一定要做檢查。
返回值的類型是 void* ,所以malloc函數(shù)并不知道開(kāi)辟空間的類型,具體在使用的時(shí)候使用者自己
來(lái)決定。
如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器。

先在堆區(qū)上動(dòng)態(tài)申請(qǐng)一定空間,使用后應(yīng)該還給操作系統(tǒng),如果不主動(dòng)還,程序結(jié)束后會(huì)自動(dòng)還,但是如果程序一直不結(jié)束,就一直“占著不用”,就會(huì)造成空間的浪費(fèi)。

2、free

用來(lái)釋放、歸還申請(qǐng)的內(nèi)存

int main()
{
	//申請(qǐng)40個(gè)字節(jié),用來(lái)存放10個(gè)整型
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//存放  1--10
	int i = 0;
	for (i = 0; i< 10; i++)
	{
		*(p + i) = i + 1;
	}
	for (i = 0; i< 10; i++)
	{
		printf("%d ", *(p+i));
	}
	//free釋放申請(qǐng)的內(nèi)存
	free(p);

	return 0;
}

用malloc申請(qǐng)后,內(nèi)存中為隨機(jī)值,使用時(shí)可給它們賦值,當(dāng)free后,又變?yōu)殡S機(jī)值。

仔細(xì)觀察,我們可以發(fā)現(xiàn),雖然這塊空間的值發(fā)生了變化,但是指針p指向的地址free前后沒(méi)有變化。因此,當(dāng)我們free還給操作系統(tǒng)后,p仍指向這塊空間。此時(shí)*p就會(huì)導(dǎo)致非法訪問(wèn),因此我們需要將p制為NULL,避免非法訪問(wèn)。

free(p);
	p = NULL;

總結(jié):malloc申請(qǐng)空間后不會(huì)初始化,使用前要判斷是否成功申請(qǐng)(是否返回NULL),使用后要free還給操作系統(tǒng),然后將用于接收這塊內(nèi)存空間的指針p置為NULL。

申請(qǐng)失敗時(shí)返回NULL,并打印錯(cuò)誤原因(沒(méi)有足夠空間)。

void? free(void * ptr)

free函數(shù)用來(lái)釋放動(dòng)態(tài)開(kāi)辟的內(nèi)存。
如果參數(shù) ptr 指向的空間不是動(dòng)態(tài)開(kāi)辟的,那free函數(shù)的行為是未定義的。
如果參數(shù) ptr 是NULL指針,則函數(shù)什么事都不做。

3、calloc

由上圖我們可以知道,malloc不會(huì)初始化,calloc會(huì)將每個(gè)元素先初始化為0,可以按需用。由于calloc需要初始化,效率比malloc稍低,此外沒(méi)有其它區(qū)別,都需要進(jìn)行相關(guān)步驟。

4、realloc

int main()
{
	int* p = (int*)malloc(5 * sizeof(int));
	if (NULL == p)
	{
		perror("malloc");
		return 1;
	}//使用
	int i = 0;
	for (i = 0; i< 5; i++)
	{
		p[i] = 1;
	}//空間不夠,增加5個(gè)整型的空間
	//此時(shí)不能用p接收
	int* ptr = (int*)realloc(p, 10 * sizeof(int));
	//先用ptr接收,再賦給p,防止返回NULL,p找不到原來(lái)的數(shù)據(jù)
	if (ptr != NULL)
	{
		p = ptr;
        ptr = NULL;//釋放但不置空,需手動(dòng)置空
	}
	//繼續(xù)使用
	for (i = 0; i< 10; i++)
	{
		printf("%d ", p[i]);
	}//realloc會(huì)把舊的空間釋放,不用自己釋放
	free(p);
	p = NULL;
}

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

1、對(duì)NULL解引用(未判斷是否為空)

2、非法訪問(wèn)內(nèi)存,越界訪問(wèn)(解引用野指針)

3、對(duì)非動(dòng)態(tài)開(kāi)辟內(nèi)存的空間用free釋放

void test()
{
int a = 10;
int *p = &a;
free(p);//ok?
}

對(duì)棧區(qū)的空間進(jìn)行釋放(x)

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

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

5、對(duì)同一塊內(nèi)存多次釋放

void test()
{
int *p = (int *)malloc(100);
free(p);
free(p);//重復(fù)釋放
}

free一個(gè)NULL空指針時(shí),什么事都不會(huì)發(fā)生。

malloc等函數(shù)是申請(qǐng)一塊空間,獲得使用它的權(quán)限,free釋放后,將權(quán)限還給操作系統(tǒng),如果再訪問(wèn)或是釋放,就是非法訪問(wèn)。
6、動(dòng)態(tài)開(kāi)辟的內(nèi)存忘記釋放(內(nèi)存泄漏)

malloc和free要成對(duì)出現(xiàn),防止出現(xiàn)內(nèi)存泄漏

int* test()
//函數(shù)內(nèi)部進(jìn)行了malloc操作,返回了malloc開(kāi)辟的空間的起始地址
//誰(shuí)接收了  要記得釋放和置空
{
	int* p = (int*)malloc(100);
	if (NULL == p)
	{
		return 1;
	}
	return p;
}
int main()
{
	int* ptr = test();
	free(ptr);
	ptr = NULL;
}
4、動(dòng)態(tài)內(nèi)存開(kāi)辟相關(guān)好題
void GetMemory(char *p)
{
    p = (char *)malloc(100);
}
void Test(void)
{
    char *str = NULL;
    GetMemory(str);
    strcpy(str, "hello world");
    printf(str);
}
int main()
{
    Test();
}

這里GetMemory函數(shù)是值傳遞,且沒(méi)有返回值,對(duì)str無(wú)影響。因此str還是指向NULL,即0地址處,然后調(diào)用strcpy需訪問(wèn)0地址處內(nèi)容,導(dǎo)致非法訪問(wèn)。

同時(shí),上面用malloc申請(qǐng)了一塊空間,但是函數(shù)內(nèi)沒(méi)有釋放,函數(shù)銷毀后,p也銷毀,這塊空間就會(huì)內(nèi)存泄漏。記得malloc要與free搭配使用。

修改后,可傳入&str,用char**p接收,*P=(char*)malloc(100),使p指向開(kāi)辟的100byte,進(jìn)而存放拷貝的內(nèi)容,打印后free(str) str=NULL

或者將p(char*)直接返回,用str接收,因?yàn)闆](méi)有free,所以malloc(100)仍然存在,進(jìn)而可以strcpy,如果此時(shí)不是malloc申請(qǐng),而是利用數(shù)組,函數(shù)銷毀后,數(shù)組的空間也會(huì)釋放,如果再進(jìn)行打印就不行了。(如下圖)這類問(wèn)題簡(jiǎn)稱為 返回??臻g地址的問(wèn)題

可以在p前面加上static使其變?yōu)殪o態(tài)區(qū)變量,函數(shù)銷毀后它不會(huì)銷毀,或者去掉[],p變?yōu)閏har*類型,即從數(shù)組變?yōu)槌A孔址?,常量字符串也是在靜態(tài)區(qū),也就是把在棧區(qū)存儲(chǔ)的數(shù)據(jù)放入靜態(tài)區(qū)中存儲(chǔ),從而避免了返回??臻g地址的問(wèn)題。

printf(str)括號(hào)內(nèi)直接加str是可以的,str是一個(gè)地址,例如printf(“hehe”),括號(hào)內(nèi)有引號(hào)+字符串,也就是首字符的地址,相當(dāng)于括號(hào)內(nèi)直接加一個(gè)地址,最終結(jié)果都是打印字符串。

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(num);
}
void Test(void)
{
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello");
    printf(str);
}
int main()
{
    Test();
}

這段代碼的整體思路沒(méi)有問(wèn)題,但是會(huì)導(dǎo)致內(nèi)存泄漏,? malloc等函數(shù)需要與free共同使用

void Test(void)
{
    char *str = (char *) malloc(100);
    strcpy(str, "hello");
    free(str);
}
    if(str != NULL)
{
    strcpy(str, "world");
    printf(str);
}

free(str)后已經(jīng)沒(méi)有權(quán)限訪問(wèn)了,但后面又調(diào)用strcpy訪問(wèn)空間,導(dǎo)致非法訪問(wèn)

開(kāi)辟--釋放--置空

習(xí)題來(lái)自《高質(zhì)量C/C++編程》

5、c/c++程序內(nèi)存開(kāi)辟示意圖

1. 棧區(qū)(stack):在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)
束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是
分配的內(nèi)存容量有限。 棧區(qū)主要存放運(yùn)行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返
回地址等。
2. 堆區(qū)(heap):一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。分
配方式類似于鏈表。
3. 數(shù)據(jù)段(靜態(tài)區(qū))(static)存放全局變量、靜態(tài)數(shù)據(jù)。程序結(jié)束后由系統(tǒng)釋放。
4. 代碼段:存放函數(shù)體(類成員函數(shù)和全局函數(shù))的二進(jìn)制代碼,只讀常量(不能被修改),字符串常量。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


文章名稱:動(dòng)態(tài)內(nèi)存分配/管理-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://weahome.cn/article/gedec.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部