老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業(yè)提供網(wǎng)站建設(shè)、域名注冊、服務(wù)器等服務(wù)

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

C語言 動(dòng)態(tài)內(nèi)存管理
  • 引言
    • C/C++程序的內(nèi)存開辟
    • 聲明
  • 一、動(dòng)態(tài)內(nèi)存管理函數(shù)
    • 1. malloc 和 free
      • 使用示例
    • 2. calloc
      • 使用示例
    • 3. realloc
      • 使用示例
    • 4. 注意事項(xiàng)
  • 二、動(dòng)態(tài)內(nèi)存管理函數(shù)使用時(shí)的錯(cuò)誤示范
    • 程序清單1
    • 程序清單2
    • 程序清單3
    • 程序清單4
    • 程序清單5
    • 程序清單6
  • 三、經(jīng)典的內(nèi)存筆試題
    • 程序清單1
    • 程序清單2
    • 程序清單3
    • 程序清單4
    • 程序清單5

成都一家集口碑和實(shí)力的網(wǎng)站建設(shè)服務(wù)商,擁有專業(yè)的企業(yè)建站團(tuán)隊(duì)和靠譜的建站技術(shù),10余年企業(yè)及個(gè)人網(wǎng)站建設(shè)經(jīng)驗(yàn) ,為成都超過千家客戶提供網(wǎng)頁設(shè)計(jì)制作,網(wǎng)站開發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營銷型網(wǎng)站建設(shè),品牌網(wǎng)站制作,同時(shí)也為不同行業(yè)的客戶提供網(wǎng)站制作、成都網(wǎng)站制作的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機(jī)械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選創(chuàng)新互聯(lián)。引言 C/C++程序的內(nèi)存開辟

1-1

1. 棧區(qū):在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限,所以有時(shí)候會(huì)出現(xiàn)棧溢出的情況。 棧區(qū)主要存放運(yùn)行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返回地址等。

2. 堆區(qū):一般由程序員分配、釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由操作系統(tǒng)回收,分配方式類似于鏈表。

3. 數(shù)據(jù)段 ( 靜態(tài)區(qū) static ) 存放全局變量、靜態(tài)數(shù)據(jù),程序結(jié)束后由系統(tǒng)釋放。

4. 代碼段:存放函數(shù)體(類成員函數(shù)和全局函數(shù))的二進(jìn)制代碼。

聲明

在我們平時(shí)寫程序時(shí),創(chuàng)建的變量都會(huì)在底層開辟內(nèi)存。C語言 的內(nèi)存布局分為三大塊:棧區(qū)、堆區(qū)、靜態(tài)區(qū)。其中棧區(qū)是我們平時(shí)使用最多的區(qū)域,棧區(qū)的使用習(xí)慣:先使用高地址處的空間,再使用低地址處的空間。然而棧區(qū)的使用總是有限的,所以本篇博客重點(diǎn)介紹如何使用堆區(qū)的內(nèi)存。

1-2

一、動(dòng)態(tài)內(nèi)存管理函數(shù) 1. malloc 和 free

malloc - memory allocate - 分配一段連續(xù)的內(nèi)存空間

void* malloc (size_t size);

// 返回值:申請內(nèi)存成功,則返回開辟好空間的頭指針;申請內(nèi)存失敗,則返回 NULL
// 參數(shù):以字節(jié)為單位的申請值

free - 釋放并回收內(nèi)存

void free (void* ptr);

// 參數(shù):ptr 為先前用 malloc、calloc 或 realloc分配的內(nèi)存塊的頭指針
// 注意:一定要是頭指針,而不是中間的指針,否則就會(huì)出現(xiàn)釋放內(nèi)存不干凈的情況
使用示例
#include#includeint main() {	int* p = (int*) malloc(40); // 申請空間

	if (p == NULL) {// 內(nèi)存分配失敗的情況
		perror("malloc");
		return 1;
	}

	for (int i = 0; i< 10; i++) {*(p + i) = i; 		// 為剛剛開辟的空間放入值
	}

	free(p);				// free 將剛剛系統(tǒng)開辟的空間,再回收掉
	p = NULL;				// 為了防止 ptr 成為野指針,所以將其置成 NULL
	return 0;
}
2. calloc

calloc - 分配一段連續(xù)的內(nèi)存空間并清零

calloc 函數(shù) 和 malloc 函數(shù)的使用思想基本相同,只不過前者在分配內(nèi)存之后,又做了清零的步驟。

void* calloc (size_t num, size_t size);

// 返回值:申請內(nèi)存成功,則返回開辟好空間的頭指針;申請內(nèi)存失敗,則返回 NULL
// 參數(shù):num 表示元素個(gè)數(shù),size 表示每個(gè)元素的字節(jié)大小
使用示例
#include#includeint main() {int* p = (int*) calloc(10, sizeof(int)); // 申請 10*4 = 40 個(gè)字節(jié)
	
	if (p == NULL) {perror("calloc");
		return 1;
	}

	for (int i = 0; i< 10; i++) {printf("%d ", *(p + i));
	}
	
	free(p); 	// 釋放
	p = NULL;

	return 0;
}

// 輸出結(jié)果:0 0 0 0 0 0 0 0 0 0
3. realloc
void* realloc (void* ptr, size_t size);

使用 realloc 再次申請分配內(nèi)存的時(shí)候,需要指定重新開辟內(nèi)存的字節(jié)總大小。假設(shè)我們之前使用 malloc / calloc 申請內(nèi)存時(shí),內(nèi)存不夠用了,realloc 就會(huì)派上用場。它可以做到很人性化地開辟內(nèi)存。

情況①:當(dāng) malloc / calloc 申請的內(nèi)存后面,有足夠的空間再次擴(kuò)充,realloc 就能夠直接接著上次的位置,繼續(xù)開辟。最終還是返回上一次開辟的原地址。

情況②:當(dāng) malloc / calloc 申請的內(nèi)存后面,沒有足夠的空間再次擴(kuò)充,realloc 也能夠另起一塊內(nèi)存區(qū)域,將之前申請的內(nèi)存中的數(shù)據(jù)也一并放入到新的內(nèi)存區(qū)域中。此時(shí)最終返回的是新的地址。

使用示例
#include#includeint main() {int* p = (int*) malloc(40);      // 1

	if (p == NULL) {perror("malloc");
		return 1;
	}

	for (int i = 0; i< 10; i++) {*(p + i) = i;
	}

	int* ptr = (int*)realloc(p, 80); // 2
	if (ptr != NULL) {		 // 3
		p = ptr;
	}
	
	free(p);						 // 4			
	p = NULL;			
	return 0;
}

// 1. malloc 申請分配內(nèi)存。

// 2. 假設(shè)空間不夠,使用 realloc 再次申請。

// 3. 由于內(nèi)存有限,所以 realloc 也有可能申請內(nèi)存失敗,當(dāng)失敗的時(shí)候就會(huì)返回 NULL. 只有當(dāng) ptr 不為空的時(shí)候,才能夠放入 p 中,這樣就能保證 p 不受影響。

// 4. 釋放內(nèi)存

4. 注意事項(xiàng)

申請內(nèi)存分配后,始終需要記得使用 free. 當(dāng)我們不釋放動(dòng)態(tài)申請的內(nèi)存的時(shí)候,如果程序結(jié)束,動(dòng)態(tài)申請的內(nèi)存由操作系統(tǒng)自動(dòng)回收;但如果程序不結(jié)束,動(dòng)態(tài)內(nèi)存是不會(huì)自動(dòng)回收的,就會(huì)形成內(nèi)存泄露的問題,久而久之,內(nèi)存就會(huì)被 " 耗干 "。

雖然現(xiàn)在的操作系統(tǒng)很智能,能夠限制一些程序的內(nèi)存使用,但還是建議標(biāo)準(zhǔn)化。

二、動(dòng)態(tài)內(nèi)存管理函數(shù)使用時(shí)的錯(cuò)誤示范 程序清單1

動(dòng)態(tài)內(nèi)存申請失敗,對 NULL 直接進(jìn)行了解引用操作。

#include#include#includeint main () {int* p = malloc(INT_MAX); // 申請失敗
	*p = 100; // error

	free(p);
	p = NULL;

	return 0;
}
程序清單2

對動(dòng)態(tài)開辟空間的越界訪問。

#include#includeint main() {int* p = malloc(40); // 開辟 40 個(gè)字節(jié)的內(nèi)存
	if (p == NULL) {perror("malloc");
		return 1;
	}

	// 越界訪問 41 ~ 44
	for (int i = 0; i< 11; i++) {*(p + i) = i;
	}

	free(p);
	p = NULL;

	return 0;
}
程序清單3

對非動(dòng)態(tài)開辟內(nèi)存使用 free 釋放.

#include#includeint main() {int a = 10;
	int* p = &a;

	free(p); // error
	p = NULL;

	return 0;
}
程序清單4

free 釋放不完整,或者 free 函數(shù)接收的指針不處于內(nèi)存開辟的頭部。

#include#includeint main() {int* p = (int*) malloc(100);
	if (p == NULL) {perror("malloc");
		return 1;
	}

	for (int i = 0; i< 10; i++) {*p = i;
		p++;
	}

	free(p); // error
	p = NULL;

	return 0;
}

從第 40 個(gè)字節(jié)后面開始釋放內(nèi)存,那么前面的內(nèi)存就未被釋放完。

1-3

程序清單5

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

#include#includeint main() {int* p = malloc(100);

	if (p == NULL) {perror("malloc");
		return 1;
	}
	
	free(p);
	free(p); // error
	p = NULL;

	return 0;
}
程序清單6

內(nèi)存泄漏。

如下程序,在 test 函數(shù)中,即使我們寫了 free,但最終走不到釋放的代碼,依然會(huì)存在內(nèi)存泄漏的問題。所以說,free 代碼的放置位置很關(guān)鍵,并不是寫了 free 就一定能夠釋放動(dòng)態(tài)內(nèi)存。

#include#includevoid test() {int* p = (int*)malloc(100);
	if (1) {return;
	}

	free(p); // 代碼走不到這一行
	p = NULL;
}

int main() {test();
	return 0;
}
三、經(jīng)典的內(nèi)存筆試題 程序清單1
#include#include#includevoid getMemory(char* p)
{p = (char*) malloc(100);
}

int main() {char* str = NULL;
	getMemory(str);
	strcpy(str, "hello world"); // 對空指針解引用

	printf(str);

	return 0;
}

分析:

在 getMemory 函數(shù)中,在堆區(qū)申請了 100 個(gè)字節(jié)的內(nèi)存大小,之后我們可以通過指針 p 來找到這些內(nèi)存。然而,在主函數(shù)中,str 始終為 NULL. 也就是說,str 并沒有指向任何一塊區(qū)域,所以后面在使用 strcpy 函數(shù)的時(shí)候," hello world " 就不能成功拷貝。

這題錯(cuò)誤的主要原因就是 str 為實(shí)參,p 為形參,對形參的操作不影響實(shí)參。

1-4

程序清單2
#include#include#includevoid getMemory(char** p, int num)
{*p = (char*) malloc(num); // 相當(dāng)于 str 指向了開辟的 100 個(gè)字節(jié)的空間
	// *(&str)<==>str = (char*) malloc(100); 
}

int main() {char* str = NULL;
	getMemory(&str, 100);
	
	strcpy(str, "hello");
	printf(str);

	free(str); 			
	str = NULL; 		

	return 0;
}

// 輸出結(jié)果: hello

分析:

程序清單2 算是 對 程序清單1 的優(yōu)化,在 getMemory 函數(shù)中,當(dāng)我們傳過去的是 str 的地址時(shí),再次對二級(jí)指針解引用,就相當(dāng)于能夠通過 str 直接找到開辟的內(nèi)存。上面的程序沒有問題,但是我們也不要忘記 free 來幫助系統(tǒng)回收內(nèi)存了。

1-5

程序清單3
#include#include#includechar* getMemory()
{char p[] = "hello world";
	return p;
}

int main() {char* str = NULL;
	str = getMemory();
	printf(str);

	return 0;
}

// 輸出結(jié)果:隨機(jī)值

分析:

數(shù)組 p 在棧區(qū)開辟了內(nèi)存,但出了 getMemory 函數(shù)后,數(shù)組中之前所占用的空間就被操作系統(tǒng)銷毀了,也就是說,剛剛棧區(qū)的內(nèi)存還給了系統(tǒng),現(xiàn)在出了函數(shù)后,即使知道這塊內(nèi)存的地址,但已經(jīng)沒有權(quán)限再次使用這塊區(qū)域了。因?yàn)閿?shù)組 p 是一個(gè)臨時(shí)的局部變量。

p 表示數(shù)組的首元素地址,假設(shè) p 的地址為 0x11223344,那么出了 getMemory 函數(shù)后,現(xiàn)在 0x11223344 指向的內(nèi)存可能已經(jīng)被其他數(shù)據(jù)占用了。所以在主函數(shù)中,當(dāng) str 再次指向 0x11223344,找到的就是一些隨機(jī)存放的數(shù)據(jù)。

1-6

程序清單4
#includeint* test() {int a = 10;
	return &a;
	// 出了 test 函數(shù),a 的地址將被系統(tǒng)回收
}

int main() {int* p = test();

	return 0;
}

程序清單4 和 程序清單3 的錯(cuò)誤思想基本相同,這是典型的 【返回棧空間地址、野指針】的問題。a 的地址出了 test 函數(shù)后,就需要被回收,所以后續(xù)在主函數(shù)中,指針 p 就沒有權(quán)限去操作這塊內(nèi)存區(qū)域。

為什么棧區(qū)的地址最后需要被回收?
答:因?yàn)楹瘮?shù)和局部變量在使用時(shí),需要在棧區(qū)開辟內(nèi)存,當(dāng)用完了,如果不被回收,那么操作系統(tǒng)的內(nèi)存遲早要被耗盡。

舉個(gè)例子:這就和住酒店一樣,當(dāng) 旅客 A 租完了房子,房子就需要打掃干凈,騰出來給后面的 旅客B / 旅客C / 旅客D… 使用。否則,房子永遠(yuǎn)不夠后面的旅客使用。如果 旅客A 前腳剛走,旅客B 就住進(jìn)去了,那么這個(gè)房子暫時(shí)屬于 旅客B 的,假設(shè) 旅客A 發(fā)現(xiàn)自己手機(jī)留在了剛剛的房子忘拿了,那么 旅客A 就需要和前臺(tái)報(bào)備一下,如果 旅客A 直接沖進(jìn)去了剛剛的房子找手機(jī),旅客B 就會(huì)告他非法訪問。

程序清單5
#includevoid test(){char* str = (char*) malloc(100);
	strcpy(str, "hello");
	free(str);
	
	if (str != NULL){		
		// 野指針,非法操作
		strcpy(str, "world");
		printf(str);
	}
}

int main() {test();
	return 0;
}

上面的代碼依舊是野指針問題,當(dāng) malloc 開辟的堆區(qū)內(nèi)存區(qū)域被 free 回收之后,str 指向的地址依舊是剛剛申請的頭部地址,但此時(shí)卻沒有了操作這塊內(nèi)存的權(quán)限。所以將 " world " 字符串放入 str 指向的區(qū)域,最終就會(huì)造成非法訪問。

綜上所述,我們應(yīng)該在 free 的后面添加如下代碼:

str = NULL; // 防止 str 成為一個(gè)野指針

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


當(dāng)前名稱:C語言動(dòng)態(tài)內(nèi)存管理-創(chuàng)新互聯(lián)
當(dāng)前地址:http://www.xueling.net.cn/article/dpogio.html

其他資訊

在線咨詢
服務(wù)熱線
服務(wù)熱線:028-86922220
TOP
主站蜘蛛池模板: 波多野结衣中文AV无码专区 | www..com在线观看 | 黄色网站免费观看视频 | 尤物yw193can在线观看 | 一区二区国产视频 | 中文字幕大看蕉永久网 | 少妇AAA级久久久无码精品片 | 动漫人物交性h的视频 | 三级网在线 | 成人免费午夜无码视频 | 亚洲AV无码国产精品久久不卡 | 国内国内在线自偷第68页 | 久久精品国产亚卅av嘿嘿 | 久久女性裸体无遮挡啪啪 | 日韩中出 | 在线1区 | 成人午夜高清 | japanese在线看 | 女人被黑人躁得好爽视频 | 少妇AAA级久久久无码精品片 | 性色a∨精品高清在线观看 久久久a | 日韩一级免费av | 久久亚洲堂色噜噜av入口网站 | 91大神xh98xh系列全部 | 可以直接看的无码AV | 成人无码A区在线观看视频 亚洲免费成人在线 | 亚洲男女视频在线观看 | 无码H黄肉动漫在线观看 | 2024丁香五月天之婷婷综合缴情 | 女人色极品影院 | 国产精品福利视频萌白酱 | 国产超碰人人模人人爽人人喊 | caop在线| www.伊人网| 日韩一级特黄毛片 | 777色淫网站女女免费 | 在线视频一二三区 | 小14萝裸体洗澡视频免费网站 | 午夜影院a | 蜜臀91| 国产欧美日韩在线观看 |