目錄
1. new/delete操作內(nèi)置類(lèi)型
2. new和delete操作自定義類(lèi)型
3. operator new與operator delete函數(shù)?
4 .new和delete的實(shí)現(xiàn)原理
1 .內(nèi)置類(lèi)型
2 .自定義類(lèi)型
new的原理
delete的原理
new T[N]的原理
delete[]的原理
5. 定位new表達(dá)式(placement-new)
6. malloc/free和new/delete的區(qū)別
7.內(nèi)存泄漏
內(nèi)存泄漏分類(lèi)
8.如何檢測(cè)內(nèi)存泄漏
9.如何避免內(nèi)存泄漏
1. new/delete操作內(nèi)置類(lèi)型
// 動(dòng)態(tài)申請(qǐng)一個(gè)int類(lèi)型的空間
int* p1 = new int;
int* p2 = new int[1];
// 動(dòng)態(tài)申請(qǐng)一個(gè)int類(lèi)型的空間并初始化為10
int* p3 = new int(10);
// 動(dòng)態(tài)申請(qǐng)10個(gè)int類(lèi)型的空間
int* p4 = new int[3];
delete p1;
delete p3;
delete[] p2;
delete[] p4;//數(shù)組申請(qǐng)數(shù)組釋放,有時(shí)候?yàn)榧嫒菪跃退闶情_(kāi)辟一個(gè)空間也用數(shù)組的方式申請(qǐng)。
2. new和delete操作自定義類(lèi)型
#include<iostream>
using namespace std;
class test {
private:
int _a;
char _b;
long _c;
public:
test()
:_a(0),
_b('0'),
_c(0)
{
cout << "test()" << endl;
}
~test()
{
cout << "~test()" << endl;
}
};
int main()
{
test A;
cout << "-----------------------------------------------------------------" << endl;
test* p = new test;
cout << "-----------------------------------------------------------------" << endl;
test* p2 = new test[10];
cout << "----------------------------------------------------------------" << endl;
delete p;
cout << "----------------------------------------------------------------" << endl;
delete []p2;
cout << "----------------------------------------------------------------" << endl;
}
?
在申請(qǐng)自定義類(lèi)型的空間時(shí),new會(huì)調(diào)用構(gòu)造函數(shù),delete會(huì)調(diào)用析構(gòu)函數(shù),而malloc與 free不會(huì)。
3. operator new與operator delete函數(shù)?
1 .operator new與operator delete函數(shù)
?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在底層通過(guò) operator delete全局函數(shù)來(lái)釋放空間。
/*
operator new:該函數(shù)實(shí)際通過(guò)malloc來(lái)申請(qǐng)空間,當(dāng)malloc申請(qǐng)空間成功時(shí)直接返回;申請(qǐng)空間
失敗,嘗試執(zhí)行空間不足應(yīng)對(duì)措施,如果這個(gè)應(yīng)對(duì)措施用戶設(shè)置了,則繼續(xù)申請(qǐng),否
則拋異常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
通過(guò)上述兩個(gè)全局函數(shù)的實(shí)現(xiàn)知道,operator new 實(shí)際也是通過(guò)malloc來(lái)申請(qǐng)空間,如果
malloc申請(qǐng)空間成功就直接返回,否則執(zhí)行用戶提供的空間不足應(yīng)對(duì)措施,如果用戶提供該措施
就繼續(xù)申請(qǐng),否則就拋異常。operator delete 最終是通過(guò)free來(lái)釋放空間的。
new和delete的實(shí)現(xiàn)原理
內(nèi)置類(lèi)型
if (_callnewh(size) == 0)
{
// report no memory
// 如果申請(qǐng)內(nèi)存失敗了,這里會(huì)拋出bad_alloc 類(lèi)型異常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
/*
operator delete: 該函數(shù)最終是通過(guò)free來(lái)釋放空間的
*/
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;
}
/*
free的實(shí)現(xiàn)
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
4 .new和delete的實(shí)現(xiàn)原理
1 .內(nèi)置類(lèi)型
如果申請(qǐng)的是內(nèi)置類(lèi)型的空間,new和malloc,delete和free基本類(lèi)似,不同的地方是:
new/delete申請(qǐng)和釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間,而且new在申 請(qǐng)空間失敗時(shí)會(huì)拋異常,malloc會(huì)返回NULL。
2 .自定義類(lèi)型
new的原理
1. 調(diào)用operator new函數(shù)申請(qǐng)空間
2. 在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造
delete的原理
1. 在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作
2. 調(diào)用operator delete函數(shù)釋放對(duì)象的空間
new T[N]的原理
1. 調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申請(qǐng)
2. 在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)
delete[]的原理
1. 在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理
2. 調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來(lái)釋放空間
5. 定位new表達(dá)式(placement-new)
定位new表達(dá)式是在已分配的原始內(nèi)存空間中調(diào)用構(gòu)造函數(shù)初始化一個(gè)對(duì)象。
使用格式:
new (place_address) type或者new (place_address) type(initializer-list) place_address必須是一個(gè)指針,initializer-list是類(lèi)型的初始化列表
使用場(chǎng)景:
定位new表達(dá)式在實(shí)際中一般是配合內(nèi)存池使用。因?yàn)閮?nèi)存池分配出的內(nèi)存沒(méi)有初始化,所以如 果是自定義類(lèi)型的對(duì)象,需要使用new的定義表達(dá)式進(jìn)行顯示調(diào)構(gòu)造函數(shù)進(jìn)行初始化。
// p1現(xiàn)在指向的只不過(guò)是與A對(duì)象相同大小的一段空間,還不能算是一個(gè)對(duì)象,因?yàn)闃?gòu)造函數(shù)沒(méi)
有執(zhí)行
A* p1 = (A*)malloc(sizeof(A));
new(p1)A; // 注意:如果A類(lèi)的構(gòu)造函數(shù)有參數(shù)時(shí),此處需要傳參
p1->~A();
free(p1);
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(10);
p2->~A();
operator delete(p2);
return 0;
6. malloc/free和new/delete的區(qū)別
malloc/free和new/delete的共同點(diǎn)是:都是從堆上申請(qǐng)空間,并且需要用戶手動(dòng)釋放。
不同的地方是:
1. malloc和free是函數(shù),new和delete是操作符
2. malloc申請(qǐng)的空間不會(huì)初始化,new可以初始化
3. malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞,new只需在其后跟上空間的類(lèi)型即可, 如果是多個(gè)對(duì)象,[]中指定對(duì)象個(gè)數(shù)即可
4. malloc的返回值為void*, 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要,因?yàn)閚ew后跟的是空間的類(lèi)型
5. malloc申請(qǐng)空間失敗時(shí),返回的是NULL,因此使用時(shí)必須判空,new不需要,但是new需 要捕獲異常
6. 申請(qǐng)自定義類(lèi)型對(duì)象時(shí),malloc/free只會(huì)開(kāi)辟空間,不會(huì)調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new 在申請(qǐng)空間后會(huì)調(diào)用構(gòu)造函數(shù)完成對(duì)象的初始化,delete在釋放空間前會(huì)調(diào)用析構(gòu)函數(shù)完成 空間中資源的清理
7.內(nèi)存泄漏
什么是內(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)。
內(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)越慢,最終卡死。
內(nèi)存泄漏分類(lèi)
C/C++程序中一般我們關(guān)心兩種方面的內(nèi)存泄漏:
堆內(nèi)存泄漏(Heap leak) 堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過(guò)malloc / calloc / realloc / new等從堆中分配的一 塊內(nèi)存,用完后必須通過(guò)調(diào)用相應(yīng)的 free或者delete 刪掉。假設(shè)程序的設(shè)計(jì)錯(cuò)誤導(dǎo)致這部分 內(nèi)存沒(méi)有被釋放,那么以后這部分空間將無(wú)法再被使用,就會(huì)產(chǎn)生Heap Leak。
系統(tǒng)資源泄漏 指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒(méi)有使用對(duì)應(yīng)的函數(shù)釋放 掉,導(dǎo)致系統(tǒng)資源的浪費(fèi),嚴(yán)重可導(dǎo)致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定。
8.如何檢測(cè)內(nèi)存泄漏
在vs下,可以使用windows操作系統(tǒng)提供的_CrtDumpMemoryLeaks() 函數(shù)進(jìn)行簡(jiǎn)單檢測(cè),但是該函數(shù)只報(bào)出了大概泄漏了多少個(gè)字節(jié),沒(méi)有其他更準(zhǔn)確的位置信息。
9.如何避免內(nèi)存泄漏
1. 工程前期良好的設(shè)計(jì)規(guī)范,養(yǎng)成良好的編碼規(guī)范,申請(qǐng)的內(nèi)存空間記著匹配的去釋放。ps: 這個(gè)理想狀態(tài)。但是如果碰上異常時(shí),就算注意釋放了,還是可能會(huì)出問(wèn)題。需要下一條智 能指針來(lái)管理才有保證。
2. 采用RAII思想或者智能指針來(lái)管理資源。
3. 有些公司內(nèi)部規(guī)范使用內(nèi)部實(shí)現(xiàn)的私有內(nèi)存管理庫(kù)。這套庫(kù)自帶內(nèi)存泄漏檢測(cè)的功能選項(xiàng)。
4. 出問(wèn)題了使用內(nèi)存泄漏工具檢測(cè)。
總結(jié): 內(nèi)存泄漏非常常見(jiàn),解決方案分為兩種:
1、事前預(yù)防型。如智能指針等。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-431006.html
2、事后查錯(cuò)型。如泄 漏檢測(cè)工具。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-431006.html
到了這里,關(guān)于C++內(nèi)存管理(new和delete)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!