網(wǎng)站建設(shè) 聯(lián)系我們教育培訓(xùn)機(jī)構(gòu)十大排名
目錄
五、C/C++內(nèi)存管理
1、C/C++內(nèi)存分布
2、C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理方式:malloc/calloc/realloc/free
3、C++內(nèi)存管理方式?
1.new/delete操作內(nèi)置類型
2.new和delete操作自定義類型?
4、operator new與operator delete函數(shù)??
5、new和delete的實(shí)現(xiàn)原理 ?
1.內(nèi)置類型
2.自定義類型
6、定位new表達(dá)式(placement-new)?
7、malloc/free和new/delete的區(qū)別
五、C/C++內(nèi)存管理
1、C/C++內(nèi)存分布
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";const char* pChar3 = "abcd";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(ptr3);
}
思考:選擇題
選項(xiàng): A.棧? ?B.堆? ?C.數(shù)據(jù)段(靜態(tài)區(qū))? ?D.代碼段(常量區(qū))
globalVar在哪里?選C? ? ? ? ? ?staticGlobalVar在哪里?選C????????staticVar在哪里?選C? ? ? ? ? ? localVar在哪里?選A??????????????num1 在哪里?選A? ? ? ? ? ? ? ? ? ? ? char2在哪里?選A
*char2在哪里?選A????????????????pChar3在哪里?選A?????????????????????*pChar3在哪里?選D? ? ? ? ? ? ? ? ptr1在哪里?選A????????????????????*ptr1在哪里?選B
- 棧又叫堆棧--非靜態(tài)局部變量/函數(shù)參數(shù)/返回值等等。
- 內(nèi)存映射段是高效的I/O映射方式,用于裝載一個(gè)共享的動(dòng)態(tài)內(nèi)存庫(kù)。用戶可使用系統(tǒng)接口創(chuàng)建共享共享內(nèi)存,做進(jìn)程間通信。
- 堆用于程序運(yùn)行時(shí)動(dòng)態(tài)內(nèi)存分配,堆是可以上增長(zhǎng)的。
- 數(shù)據(jù)段--存儲(chǔ)全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)。
- 代碼段--可執(zhí)行的代碼/只讀常量。
2、C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理方式:malloc/calloc/realloc/free
void Test ()
{// 1.malloc/calloc/realloc的區(qū)別是什么?int* p2 = (int*)calloc(4, sizeof (int));int* p3 = (int*)realloc(p2, sizeof(int)*10);// 這里需要free(p2)嗎?free(p3 );
}
calloc的作用:創(chuàng)建空間,然后初始化
malloc、calloc 和 realloc 都是 C 語(yǔ)言中的內(nèi)存分配函數(shù),它們的主要區(qū)別在于:
malloc():分配指定大小的內(nèi)存塊,但不進(jìn)行初始化,內(nèi)存塊中的內(nèi)容是隨機(jī)的。
calloc():分配指定大小的內(nèi)存塊,并將其初始化為 0。
realloc():重新分配已分配的內(nèi)存塊的大小。如果新的大小比舊的大小更大,則會(huì)分配新的內(nèi)存塊并復(fù)制舊內(nèi)存塊的內(nèi)容到新的內(nèi)存塊中。如果新的大小比舊的大小更小,則會(huì)將舊內(nèi)存塊的內(nèi)容復(fù)制到新的內(nèi)存塊中,并釋放多余的內(nèi)存。
3、C++內(nèi)存管理方式?
1.new/delete操作內(nèi)置類型
void Test()
{// 動(dòng)態(tài)申請(qǐng)一個(gè)int類型的空間int* ptr4 = new int;// 動(dòng)態(tài)申請(qǐng)一個(gè)int類型的空間并初始化為10int* ptr5 = new int(10);// 動(dòng)態(tài)申請(qǐng)10個(gè)int類型的空間int* ptr6 = new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}
動(dòng)態(tài)申請(qǐng)new一個(gè)數(shù)組,后面若沒(méi)有想要放進(jìn)去的數(shù)據(jù)的話,就以0來(lái)填充。
2.new和delete操作自定義類型?
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}private:int _a;
};int main()
{// new/delete 和 malloc/free最大區(qū)別是 new/delete對(duì)于【自定義類型】除了開(kāi)空間還會(huì)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(1);free(p1);delete p2;// 內(nèi)置類型是幾乎是一樣的int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;A* p5 = (A*)malloc(sizeof(A)*10);A* p6 = new A[10];free(p5);delete[] p6;return 0;
}
????????在申請(qǐng)自定義類型的空間時(shí),new會(huì)調(diào)用構(gòu)造函數(shù),若有定義中的缺省值,則在動(dòng)態(tài)申請(qǐng)new一個(gè)數(shù)組,后面沒(méi)有元素填充時(shí),會(huì)自動(dòng)將缺省值填充到數(shù)組里面去。
4、operator new與operator delete函數(shù)??
operator delete全局函數(shù)來(lái)釋放空間。
以下是某個(gè)版本的原碼:
/*
operator new:該函數(shù)實(shí)際通過(guò)malloc來(lái)申請(qǐng)空間,當(dāng)malloc申請(qǐng)空間成功時(shí)直接返回;申請(qǐng)空間
失敗,嘗試執(zhí)行空 間不足應(yīng)對(duì)措施,如果改應(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)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: 該函數(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_FINALLYreturn;
}/*
free的實(shí)現(xiàn)
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
5、new和delete的實(shí)現(xiàn)原理 ?
1.內(nèi)置類型
2.自定義類型
void Func()
{int* p1 = new int[1024 * 1024 * 100];cout << p1 <<endl;int* p2 = new int[1024 * 1024 * 100];cout << p2 <<endl;int* p3 = new int[1024 * 1024 * 100];cout << p3 <<endl;int* p4 = new int[1024 * 1024 * 100];cout << p4 <<endl;int* p5 = new int[1024 * 1024 * 100];cout << p5 <<endl;
}int main()
{try{Func();}catch(const exception& e){cout << e.what() << endl;}return 0;
}
6、定位new表達(dá)式(placement-new)?
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}private:int _a;
};// 定位new/replacement new
int main()
{// 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類的構(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;
}
STL底層源碼剖析:
注意:第一,不要忘記釋放;第二,不要交錯(cuò)使用。
????????若是注釋部分運(yùn)行,則是沒(méi)有了構(gòu)造和析構(gòu)部分,使得operator new和operator delete部分成為野指針,指向隨機(jī)值。
7、malloc/free和new/delete的區(qū)別
- malloc和free是函數(shù),new和delete是操作符。
- malloc申請(qǐng)的空間不會(huì)初始化,new可以初始化。
- malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞,new只需在其后跟上空間的類型即可, 如果是多個(gè)對(duì)象,[]中指定對(duì)象個(gè)數(shù)即可。
- malloc的返回值為void*, 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要,因?yàn)閚ew后跟的是空間的類型。
- malloc申請(qǐng)空間失敗時(shí),返回的是NULL,因此使用時(shí)必須判空,new不需要,但是new需 要捕獲異常。
- 申請(qǐng)自定義類型對(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ù)完成 空間中資源的清理釋放。