国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

C++內(nèi)存管理

mudiyouyou / 1998人閱讀

摘要:對(duì)于申請(qǐng)內(nèi)存失敗,的處理是返回空指針,而的處理是拋異常對(duì)于自定義類型,會(huì)調(diào)用其構(gòu)造析構(gòu)函數(shù),而不會(huì)。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。

前言:本章主要介紹C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語(yǔ)言的內(nèi)存管理方式(new delete對(duì)比 malloc free),最后為了加深讀者的理解,會(huì)介紹new和delete的底層實(shí)現(xiàn)原理。



1.C/C++中程序內(nèi)存分布

C/C++中程序內(nèi)存區(qū)域大致劃分為:內(nèi)核空間(這部分用戶不能讀寫)、棧、內(nèi)存映射段、堆、數(shù)據(jù)段(存儲(chǔ)全局?jǐn)?shù)據(jù)、靜態(tài)數(shù)據(jù))、代碼段(存儲(chǔ)可執(zhí)行代碼、只讀常量,又稱常量區(qū))。

1.1 內(nèi)存分布圖

1.2 小試牛刀

接下來(lái)看下如下代碼,思考下每一個(gè)變量分別在哪個(gè)內(nèi)存區(qū)域?

int globalVar = 1;static int staticGlobalVar = 1;void test(){	static int staticVar = 1;	int localVar = 1;	int num1[10] = { 1,2,3,4 };	char char2[] = "abcd";	char *pchar3 = "abcd";//有的編譯器會(huì)報(bào)錯(cuò),需要用const char 	int* ptr1 = (int*)malloc(sizeof(int) * 4);	int* ptr2 = (int*)calloc(4,sizeof(int));	int* ptr3 = (int*)realloc(ptr2,sizeof(int) * 4);	free(ptr1);	free(ptr2);}

上述代碼段對(duì)應(yīng)變量區(qū)域劃分如下:


2.C語(yǔ)言部分的動(dòng)態(tài)內(nèi)存管理方式

再來(lái)回顧一下之前C語(yǔ)言部分的動(dòng)態(tài)內(nèi)存管理方式:malloc / calloc/ realloc和free

帶著兩個(gè)問題閱讀下述程序段:

1.malloc / calloc/ realloc的區(qū)別是什么?

2.最后需要free(p2)嗎?

void Test(){	int* p1 = (int*)malloc(sizeof(int));	free(p1);	int* p2 = (int*)calloc(4, sizeof(int));	int* p3 = (int*)realloc(p2, sizeof(int) * 10);	free(p3);}

答:

1.calloc相當(dāng)于malloc+memset(0),即開空間+初始化。

2.realloc是對(duì)malloc/calloc的空間進(jìn)行擴(kuò)容,擴(kuò)容之下又涉及到了咱們前面所講的原地?cái)U(kuò)容和異地?cái)U(kuò)容倆種情景:原地?cái)U(kuò)容p2和p3是一樣的,也有可能是異地?cái)U(kuò)容,那么p2指向的空間已經(jīng)被釋放了,所以兩種情況下我們都可以不需要處理p2。


3.C++內(nèi)存管理方式

總之就是C語(yǔ)言那套內(nèi)存管理方式相對(duì)麻煩,所以C++提出了自己的內(nèi)存管理方式:通過new和delete操作符進(jìn)行動(dòng)態(tài)內(nèi)存管理.

3.1new/delete操作內(nèi)置類型

1.開辟單個(gè)元素

開辟單個(gè)元素基本語(yǔ)法: type * ptr = new type(content); ,可以理解成動(dòng)態(tài)申請(qǐng)一個(gè)type類型的空間并將其中內(nèi)容初始化為content,當(dāng)然,你也可以選擇不初始化。

釋放空間語(yǔ)法: delete name;

例:

int* a = new int(100);  //動(dòng)態(tài)申請(qǐng)一個(gè)int類型的空間并初始化為100delete a;

2.開辟n個(gè)type類型的空間

開辟n個(gè)type類型基本語(yǔ)法: type* name = new type[n]

刪除的基本語(yǔ)法:delete[] name;

例:

int* ptr = new int[100];//動(dòng)態(tài)申請(qǐng)100個(gè)int類型的空間delete[] ptr;           //注意哦!一定要匹配哦!不然必崩潰!

3.對(duì)于內(nèi)置類型,malloc/free和new/delete確實(shí)沒有什么區(qū)別,二者的作用完全一樣。

例:

int main(){	//malloc向內(nèi)存申請(qǐng)4個(gè)整型大小的空間	int* p1 = (int*)malloc(sizeof(int) * 4);	//new向內(nèi)存申請(qǐng)4個(gè)整型大小的空間	int* p2 = new int[4];	//free釋放掉p1申請(qǐng)的空間	free(p1);	p1 = nullptr;	//delete釋放掉p2申請(qǐng)的空間	delete[] p2;	return 0;}


3.2 new/delete操作自定義類型

class  Date{public:	Date(int year=2021, int month=1, int day=1)	{		_year = year;		_month = month;		_day = day;	}private:	int _year;	int _month;	int _day;};int main(){	//malloc申請(qǐng)十個(gè)Date空間	Date* p1 = (Date*)malloc(sizeof(Date) * 10);	free(p1);	//new申請(qǐng)十個(gè)Date空間	Date* p2 = new Date[10];	delete[] p2;	return 0;}

區(qū)別:在申請(qǐng)自定義類型空間的時(shí)候,new會(huì)調(diào)用構(gòu)造函數(shù),delete會(huì)調(diào)用析構(gòu)函數(shù),而mallo和free不會(huì)哦!


4.new和delete底層實(shí)現(xiàn)原理(important!!!)

在講解他們的底層實(shí)現(xiàn)原理之前需要先先介紹一下兩個(gè)全局函數(shù),分別是operator newoperator delete.

new和delete是用戶進(jìn)行動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放的操作符,operator new和operator delete是系統(tǒng)提供的全局函數(shù),new在底層調(diào)用operator new全局函數(shù)來(lái)申請(qǐng)空間,delete在底層通過調(diào)用operator delete全局函數(shù)來(lái)釋放空間。


4.1operator new/operator delete

operator new封裝了 malloc 和失敗拋異常倆個(gè)部分,

下面是operator new的代碼:

void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc){	// try to allocate size bytes	void* p;	while ((p = malloc(size)) == 0)              //如果開辟成功就不會(huì)進(jìn)入循環(huán),并且可以清晰		if (_callnewh(size) == 0)		{			// report no memory			// 如果申請(qǐng)內(nèi)存失敗了,這里會(huì)拋出bad_alloc 類型異常			static const std::bad_alloc nomem;			_RAISE(nomem);		}	return (p);}

類似的,operator delete封裝了free

下面是operator delete的代碼:

void operator delete(void* pUserData){	_CrtMemBlockHeader* pHead;	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));	if (pUserData == NULL)		return;	_mlock(_HEAP_LOCK); /* block other threads */	__TRY		/* get a pointer to memory block header */		pHead = pHdr(pUserData);	/* verify block type */	_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));	_free_dbg(pUserData, pHead->nBlockUse);	__FINALLY		_munlock(_HEAP_LOCK); /* release other threads */	__END_TRY_FINALLY		return;}

總結(jié):通過觀察上述倆個(gè)全局函數(shù)的實(shí)現(xiàn),不難發(fā)現(xiàn)operator new實(shí)際也是通過malloc來(lái)申請(qǐng)空間,如果malloc申請(qǐng)空間成功就直接返回,否則執(zhí)行用戶提供的空間不足應(yīng)對(duì)措施,如果用戶提供該措施就繼續(xù)申請(qǐng),否則就拋異常,operator delete最終是通過free來(lái)釋放空間的。


4.2new和delete的實(shí)現(xiàn)原理

內(nèi)置類型

malloc/free與new/delete在處理內(nèi)置類型時(shí)并沒有區(qū)別,只是malloc申請(qǐng)空間失敗時(shí)返回空指針,而new申請(qǐng)空間時(shí)是拋異常,new/delete申請(qǐng)和釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間。

自定義類型

1.new的原理:1.調(diào)用operator new函數(shù)申請(qǐng)空間。2.在申請(qǐng)空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的初始化。

2.delete的原理:1.在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作。2.調(diào)用operator delete函數(shù)釋放空間。

另外new T[N]的原理:調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用N次operator new函數(shù)完成N個(gè)對(duì)象空間的申請(qǐng),然后在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)。**delete[]的原理:**在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理。然后調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用N次operator delete來(lái)釋放空間。


初學(xué)者看到“delete調(diào)用析構(gòu)函數(shù),完成對(duì)象資源的清理工作,后邊又調(diào)用operator delete函數(shù)釋放空間”這部分內(nèi)容時(shí)可能會(huì)比較混亂,這里以棧為例子詳細(xì)說下:

struct Stack{	int* _a;	int _top;	int _capacity;	Stack(int capacity = 4)		:_a(new int[capacity])		,_size(0)		,_capacity(capacity)	{		cout << "Stack(int capacity = 4)" << endl;	}	~Stack()	{		delete _a;		_top = _capacity = 0;		cout << "~Stack()" << endl;	}};int main(){	Stack st;	Stack* ps = new Stack;	delete ps;	return 0;}

首先,創(chuàng)建st變量,存放在棧當(dāng)中,然后調(diào)用構(gòu)造函數(shù)_a申請(qǐng)空間(對(duì)應(yīng)上圖動(dòng)作1)。

接著,對(duì)于ps,會(huì)先去堆上調(diào)用operator new開辟一塊空間(對(duì)應(yīng)上圖動(dòng)作2),再調(diào)用構(gòu)造函數(shù)對(duì)對(duì)象進(jìn)行初始化,初始化時(shí)_a又會(huì)申請(qǐng)空間(對(duì)應(yīng)上圖動(dòng)作3)

最后,delete[] ps,會(huì)先調(diào)用析構(gòu)函數(shù)完成對(duì)象資源的清理,即釋放_(tái) a申請(qǐng)的空間,然后調(diào)用operator delete釋放ps申請(qǐng)的空間,然后調(diào)用析構(gòu)函數(shù) _ a申請(qǐng)的空間。(就是步驟321)


5.相關(guān)面經(jīng)

5.1malloc/free與new/delete的區(qū)別

1.malloc/free是函數(shù),而new/delete是操作符。

2.malloc申請(qǐng)的空間不會(huì)初始化,而new申請(qǐng)的空間可以初始化(內(nèi)置類型new也不會(huì)初始化)。

3.malloc申請(qǐng)空間時(shí)需要手動(dòng)計(jì)算要申請(qǐng)的空間的字節(jié)數(shù),而new申請(qǐng)空間只需要所申請(qǐng)的類型即可。

4.malloc的返回值為void*,使用是需要強(qiáng)制類型轉(zhuǎn)換,而new不需要,因?yàn)閚ew跟的是空間的類型。

5.對(duì)于申請(qǐng)內(nèi)存失敗,malloc的處理是返回空指針NULL,而new的處理是拋異常

6.對(duì)于自定義類型,new/delete會(huì)調(diào)用其構(gòu)造/析構(gòu)函數(shù),而malloc/delete不會(huì)。


5.2什么是內(nèi)存泄漏?

內(nèi)存泄漏指因?yàn)槭韬龌蝈e(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。


5.3內(nèi)存泄漏的危害

如果是長(zhǎng)期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺(tái)服務(wù)等等,出現(xiàn)內(nèi)存泄漏會(huì)導(dǎo)致響應(yīng)越來(lái)越慢,最終卡死。

比如王者榮耀后臺(tái)服務(wù),長(zhǎng)期運(yùn)行,只有升級(jí)的時(shí)候才會(huì)停,內(nèi)存泄漏會(huì)導(dǎo)致可用內(nèi)存越來(lái)越少,程序越來(lái)越慢,甚至掛掉。

再比如物聯(lián)網(wǎng)設(shè)備:各種智能家居、智能機(jī)器人等等,它們內(nèi)存很小,也經(jīng)不起內(nèi)存泄漏的折騰。

by the way,對(duì)于C++我們需要主動(dòng)釋放內(nèi)存,但是在Java當(dāng)中,不再需要主動(dòng)釋放內(nèi)存,Java后臺(tái)有垃圾回收器,接管了內(nèi)存釋放(所以Java寫得好舒服,嗚嗚嗚)


5.4如何預(yù)防內(nèi)存泄漏(先了解一下,后續(xù)作者再詳細(xì)介紹)

1.智能指針

2.內(nèi)存泄漏檢測(cè)工具

2.1在linux環(huán)境下:

2.2在Windows環(huán)境下使用第三方工具:VLD工具

原理:以Visual Leak Detector為例,其工作分為3步,首先在初始化注冊(cè)一個(gè)鉤子函數(shù);然后在內(nèi)存分配時(shí)該鉤子函數(shù)被調(diào)用以記錄下當(dāng)時(shí)的現(xiàn)場(chǎng);最后檢查堆內(nèi)存分配鏈表以確定是否存在內(nèi)存泄漏并將泄漏內(nèi)存的現(xiàn)場(chǎng)轉(zhuǎn)換成可讀的形式輸出。



感謝您的閱讀!!!如果內(nèi)容對(duì)你有幫助的話,記得給我三連(點(diǎn)贊、收藏、關(guān)注)——做個(gè)手有余香的人。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/123952.html

相關(guān)文章

  • 比較C++、Java、Delphi聲明類對(duì)象時(shí)候的相關(guān)語(yǔ)法和原理

    摘要:但是在中就只是聲明,但是還沒有分配空間,中的才是分配了內(nèi)存的。對(duì)于語(yǔ)言會(huì)報(bào)錯(cuò)這樣是對(duì)的詳細(xì)說明原因只能是或者是沒有這個(gè)是中的語(yǔ)法,所以要區(qū)分和的語(yǔ)法和機(jī)制如果用聲明了對(duì)象會(huì)報(bào)錯(cuò)這才是正確的語(yǔ)法 C++中創(chuàng)建對(duì)象的兩種語(yǔ)法 在c++的類中,我如果要訪問類中的成員變量或函數(shù),有2種方法,第一種就是定義一個(gè)一個(gè)對(duì)象,如: Class A ... A aa; aa.xxx(); 另外一種就是...

    gaosboy 評(píng)論0 收藏0
  • 系統(tǒng)地學(xué)習(xí)C++

    摘要:本書主要圍繞一系列逐漸復(fù)雜的程序問題,以及用以解決這些問題的語(yǔ)言特性展開講解。你不只學(xué)到的函數(shù)和結(jié)構(gòu),也會(huì)學(xué)習(xí)到它們的設(shè)計(jì)目的和基本原理。因此我們把精力集中在最有價(jià)值的地方。本書不僅是對(duì)模板的權(quán)威解釋,而且本書還深入地介紹了其他一般的思想。 C++ 入門教程(41課時(shí)) - 阿里云大學(xué) C+...

    joyqi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<