觀侯捷老師new和delete以及malloc在vc當中調試模式和運行下分配內存

在講到new和delete不得不想到c語言中的malloc and free 以及其經常用於動態內存分配,而簡單來說,動態內存分配在堆中,不會因爲離開作用域而刪除,而棧中存儲的一般爲函數參數,返回值以及作用域下的local orient.

那我們可想而知的是,在函數中如果我創建指針,肯定爲了不浪費內存,我們選擇動態分配內存的方式,那麼就是利用C++中的new或者c中的malloc,我們需要養成一個良好的習慣就是記得釋放內存不然會造成memory leak,想必大家經常聽過這個詞,那這裏是爲什麼會造成內存泄漏,假設我們在一個作用域比如

{
    char* p = new char[3];
}

此時我們創建了一個指向char型的指針p,但是p沒有delete,這時候,一塊在heap中創建的char數組依舊存在,而這個地址的別名p因爲離開了作用域而無法訪問,那麼這塊內存在整個操作系統中就是無法使用的部分。

所以在內存中,我們使用了new就得伴隨着delete。

這時候我們知道p是一個local orient,那麼我們還會有一種寫法就是static,也就是靜態對象或者說全局對象,這種對象在離開作用域時,是不會消失的,他會伴隨着程序結束而終結。

{
    static int a = 3;
}
那麼說到這裏,我們也會去想知道new到底是怎麼工作的,從我的上一篇博客裏,我們知道創建一個complex對象需要2個double也就是8個字節,這時候比如有下列的程序
{
    complex* p = new complex(0,0);
}
這時候我們使用new創建了指向complex(0,0)對象的指針p,而new是先爲complex對象分配內存,也就是malloc一個內存大小爲sizeof(complex)的堆大小給p指針,然後再在這地址上調用complex的構造函數,創建complex對象。

同樣的delete的工作過程正好相反,delete先調用了析構函數刪除了complex對象,然後再delete掉p指針所指向的內存,這時候我們發現好像complex調用不調用析構函數好像沒有什麼影響,我直接delete掉p的內存,也不會有memory leak啊,相信很多人會這樣想,侯捷老師在視頻中也沒有這麼說,但是我的理解就是確實沒有影響,但是是因爲他是complex,沒有指針進行動態分配內存,假設我分配了內存,一個char*指向了堆裏的另外一個地方,操作系統會知道我這塊內存有人用了,誰用的我也不知道了,delete已經把它幹掉了,別問我。這樣是不是就造成內存泄漏了,所以delete要先把對象析構掉,再delete釋放內存。

那麼講了這麼多new和delete我們未必知道new會new出多少內存出來,new一個complex就一定出現一個complex的大小嗎?


從上圖,我們可以看到malloc一個對象的時候,不僅僅只有這個對象的大小,還有在Debug mode下的Debug header在complex對象上面有8個內存單元,下有一個內存單元,然後有表示這塊內存大小的最上端和最下端的2個cookis,通過計算髮現其值爲8+(4*8+4*1)+(4*2)爲52 而在vc當中存儲大小一般都爲16的倍數,所以填充3個pad到64,這時候cookis記錄下大小爲60,最後4位爲預留的4位,一般都是0,可以用來表示內存是不是已經分配出去,所以改爲61表示已經分配出去64字節.

同樣的在realise mode下,沒有debug header,這時候complex爲8字節,加上cookis的4*2個字節,正好是16,不用填充,修改cookis爲11,表示已經分配出去。


如果我們new了一個array 對象那麼該怎麼表示,那麼在上述的一個對象上,我們必須給一個內存單元來記錄這個數組裏面有幾個對象,所以算的其值後還會加上這個內存單元,但是這裏我覺得我們更應該關注的是delete的時候,如果不加[]爲什麼會造成memory leak,如果單單使用一個delete,我們知道的是系統默認其只有一個對象,調用這個對象的析構函數,然後delete釋放了這塊cookis表示的內存,沒問題,至少在系統看來是這樣的,對於complex,從我上面對new和delete聯想分析一下,確實沒問題,也沒有被標記使用的內存沒有釋放,ok,但是如果含有指針的對象,指針指向了heap裏面的一塊內存,那塊內存沒有釋放的話,就是內存泄漏了,所以要加上[]以便系統識別,養成一個好習慣。

發佈了33 篇原創文章 · 獲贊 16 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章