激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++ 內存管理原理分析

C++ 內存管理原理分析

2022-02-28 14:52林慢慢腦瓜子嗡嗡的 C/C++

本章主要介紹C++的內存管理,以C++的內存分布作為引入,介紹C++不同于C語言的內存管理方式(new delete對比 malloc free),最后為了加深讀者的理解,會介紹new和delete的底層實現原理

1.C/C++中程序內存分布

C/C++中程序內存區域大致劃分為:內核空間(這部分用戶不能讀寫)、棧、內存映射段、堆、數據段(存儲全局數據、靜態數據)、代碼段(存儲可執行代碼、只讀常量,又稱常量區)。

1.1 內存分布圖

C++ 內存管理原理分析

1.2 小試牛刀

接下來看下如下代碼,思考下每一個變量分別在哪個內存區域?

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";//有的編譯器會報錯,需要用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);
}

上述代碼段對應變量區域劃分如下:

C++ 內存管理原理分析

 

2.C語言部分的動態內存管理方式

再來回顧一下之前C語言部分的動態內存管理方式:malloc / calloc/ realloc和free

帶著兩個問題閱讀下述程序段:

1.malloc / calloc/ realloc的區別是什么?

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相當于malloc+memset(0),即開空間+初始化。

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

C++ 內存管理原理分析

 

3.C++內存管理方式

總之就是C語言那套內存管理方式相對麻煩,所以C++提出了自己的內存管理方式:通過new和delete操作符進行動態內存管理.

3.1new/delete操作內置類型

1.開辟單個元素

開辟單個元素基本語法: type * ptr = new type(content); ,可以理解成動態申請一個type類型的空間并將其中內容初始化為content,當然,你也可以選擇不初始化。

釋放空間語法: delete name;

例:

int* a = new int(100);  //動態申請一個int類型的空間并初始化為100
delete a;

2.開辟n個type類型的空間

開辟n個type類型基本語法: type* name = new type[n]

刪除的基本語法:delete[] name;

例:

int* ptr = new int[100];//動態申請100個int類型的空間
delete[] ptr;           //注意哦!一定要匹配哦!不然必崩潰!

3.對于內置類型,malloc/free和new/delete確實沒有什么區別,二者的作用完全一樣。

例:

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

C++ 內存管理原理分析

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申請十個Date空間
	Date* p1 = (Date*)malloc(sizeof(Date) * 10);
	free(p1);

	//new申請十個Date空間
	Date* p2 = new Date[10];
	delete[] p2;

	return 0;
}

區別:在申請自定義類型空間的時候,new會調用構造函數,delete會調用析構函數,而mallo和free不會哦!

 

4.new和delete底層實現原理(important!!!)

C++ 內存管理原理分析

在講解他們的底層實現原理之前需要先先介紹一下兩個全局函數,分別是operator new 和operator delete.

new和delete是用戶進行動態內存申請和釋放的操作符,operator new和operator delete是系統提供的全局函數,new在底層調用operator new全局函數來申請空間,delete在底層通過調用operator delete全局函數來釋放空間。

4.1operator new/operator delete

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

下面是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)              //如果開辟成功就不會進入循環,并且可以清晰
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申請內存失敗了,這里會拋出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;
}

總結:通過觀察上述倆個全局函數的實現,不難發現operator new實際也是通過malloc來申請空間,如果malloc申請空間成功就直接返回,否則執行用戶提供的空間不足應對措施,如果用戶提供該措施就繼續申請,否則就拋異常,operator delete最終是通過free來釋放空間的。

4.2new和delete的實現原理

內置類型

malloc/free與new/delete在處理內置類型時并沒有區別,只是malloc申請空間失敗時返回空指針,而new申請空間時是拋異常,new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請的是連續空間。

自定義類型

1.new的原理:1.調用operator new函數申請空間。2.在申請空間上執行構造函數,完成對象的初始化。

2.delete的原理:1.在空間上執行析構函數,完成對象中資源的清理工作。2.調用operator delete函數釋放空間。

另外new T[N]的原理:調用operator new[]函數,在operator new[]中實際調用N次operator new函數完成N個對象空間的申請,然后在申請的空間上執行N次構造函數。**delete[]的原理:**在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理。然后調用operator delete[]釋放空間,實際在operator delete[]中調用N次operator delete來釋放空間。

初學者看到“delete調用析構函數,完成對象資源的清理工作,后邊又調用operator delete函數釋放空間”這部分內容時可能會比較混亂,這里以棧為例子詳細說下:

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;
}

C++ 內存管理原理分析

首先,創建st變量,存放在棧當中,然后調用構造函數_a申請空間(對應上圖動作1)。

接著,對于ps,會先去堆上調用operator new開辟一塊空間(對應上圖動作2),再調用構造函數對對象進行初始化,初始化時_a又會申請空間(對應上圖動作3)

最后,delete[] ps,會先調用析構函數完成對象資源的清理,即釋放_ a申請的空間,然后調用operator delete釋放ps申請的空間,然后調用析構函數 _ a申請的空間。(就是步驟321)

 

5.相關面經

5.1malloc/free與new/delete的區別

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

2.malloc申請的空間不會初始化,而new申請的空間可以初始化(內置類型new也不會初始化)。

3.malloc申請空間時需要手動計算要申請的空間的字節數,而new申請空間只需要所申請的類型即可。

4.malloc的返回值為void*,使用是需要強制類型轉換,而new不需要,因為new跟的是空間的類型。

5.對于申請內存失敗,malloc的處理是返回空指針NULL,而new的處理是拋異常

6.對于自定義類型,new/delete會調用其構造/析構函數,而malloc/delete不會。

5.2什么是內存泄漏?

內存泄漏指因為疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏并不是指內存在物理上的消失,而是應用程序分配某段內存后,因為設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。

C++ 內存管理原理分析

5.3內存泄漏的危害

如果是長期運行的程序出現內存泄漏,影響很大,如操作系統、后臺服務等等,出現內存泄漏會導致響應越來越慢,最終卡死。

比如王者榮耀后臺服務,長期運行,只有升級的時候才會停,內存泄漏會導致可用內存越來越少,程序越來越慢,甚至掛掉。

再比如物聯網設備:各種智能家居、智能機器人等等,它們內存很小,也經不起內存泄漏的折騰。

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

5.4如何預防內存泄漏(先了解一下,后續作者再詳細介紹)

1.智能指針

2.內存泄漏檢測工具

2.1在linux環境下:

C++ 內存管理原理分析

2.2在Windows環境下使用第三方工具:VLD工具

C++ 內存管理原理分析

原理:以Visual Leak Detector為例,其工作分為3步,首先在初始化注冊一個鉤子函數;然后在內存分配時該鉤子函數被調用以記錄下當時的現場;最后檢查堆內存分配鏈表以確定是否存在內存泄漏并將泄漏內存的現場轉換成可讀的形式輸出。

感謝您的閱讀?。?!如果內容對你有幫助的話,記得給我三連(點贊、收藏、關注)――做個手有余香的人。

到此這篇關于C++ 內存管理原理分析的文章就介紹到這了,更多相關C++ 內存管理內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/weixin_48953972/article/details/121402222

延伸 · 閱讀

精彩推薦
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
主站蜘蛛池模板: 欧美在线日韩 | 亚洲成人入口 | 久久精品日产第一区二区三区 | 精品久久久久久国产 | 久久人人爽人人爽人人片av高请 | 久久精品一区二区三区不卡牛牛 | 国产精品视频2021 | 亚洲射逼 | 福利在线免费视频 | 永久久久 | 一级@片| 鲁丝一区二区三区不属 | 亚洲一区二区网址 | 第一区免费在线观看 | 国产日产精品久久久久快鸭 | 国产精品成人一区 | 欧美人xx| 国产亚洲精品一区二区三区 | 久草在线高清 | av成人一区二区 | 成年免费在线视频 | 免费毛片免费看 | 久久精品视频7 | 久久777国产线看观看精品 | 久久久久久麻豆 | av在线等| 日本久久网站 | 在线成人一区二区 | 91经典视频 | av在线一区二区三区四区 | 国产pron| 亚洲啊v在线观看 | 成人毛片视频在线观看 | 成人在线免费观看小视频 | 羞羞色院91精品网站 | 成人免费一区二区三区 | 国产精品久久久久久久久久了 | 久久久久久麻豆 | 日产精品久久久一区二区福利 | 91成人在线免费视频 | 欧美性激情视频 |