淺析C++中的new operator

淺析C++中的new operator

因爲這幾天想模擬vector,但是對C++的內存管理機制不太瞭解,所以近段時間一直在關注並搜索着相關信息,我會在我的博客中陸續把成果寫出來,以供大家參考。

經過查閱資料,發現C++new系統類型和用戶自定義的類型時對內存的分配是不一樣的。我們看下邊的一段代碼:

輸出中的size16,讀者可能會有疑問,爲什麼不是12?先讓我們想這麼一個問題,new 和 delete 應該是成對使用的,當我們new了一個四個元素的int數組的時候,delete將要做什麼工作?對,是將這16個字節(x86環境下)釋放,但是,當我們new了一個用戶的自定義類型的數組呢?需要釋放多少個字節?不太好說,所以我們需要在新開闢的這段內存中存儲相關的信息,用來保存新開闢內存的大小。

但是當我們把析構函數註釋掉以後,結果又不一樣了,動態申請的僅僅是12個字節,從網上搜索資料,需要多分配字節的有以下三種情況:

顯式的聲明瞭析構函數的

擁有需要調用析構函數的類的成員的

繼承自需要調用析構函數的類的

以下摘自http://apps.hi.baidu.com/share/detail/2188389

下面運行這樣一段代碼做個實驗:

我們直接來看VC2005Release版本的運行結果,DEBUG版因包含了較多的調試信息,這裏就不分析了:

alloc 0 bytes, address=003A36F0 distance=3815152

alloc 4 bytes, address=003A3700 distance=16

alloc 8 bytes, address=003A3710 distance=16

alloc 12 bytes, address=003A3720 distance=16

alloc 16 bytes, address=003A3738 distance=24

alloc 20 bytes, address=003A84C0 distance=19848

alloc 24 bytes, address=003A84E0 distance=32

alloc 28 bytes, address=003A8500 distance=32

alloc 32 bytes, address=003A8528 distance=40

alloc 36 bytes, address=003A8550 distance=40

每一次分配的字節數都比上一次多4distance值記錄着與上一次分配的差值,第一個差值沒有實際意義,中間有一個較大的差值,可能是這塊內存已經被分配了,於是也忽略它。結果中最小的差值爲16字節,直到我們申請16字節時,這個差值變成了24,後面也有類似的規律,那麼我們可以認爲申請所得的內存結構是如下這樣的:

從圖中不難看出,當我們要分配一段內存時,所得的內存地址和上一次的尾地址至少要相距8個字節(在DEBUG版中還要更多),那麼我們可以猜想,這8個字節中應該記錄着與這段所分配的內存有關的信息。觀察這8個節內的內容,得到結果如下:

圖中右邊爲每次分配所得的地址之前8個字節的內容的16進製表示,從圖中紅線所表示可以看到,這8個字節中的第一個字節乘以8即得到相臨兩次分配時的距離,經過試驗一次性分配更大的長度可知,第二個字節也是這個意義,並且代表高8位,也就說前面空的這8個字節中的前兩個字節記錄了一次分配內存的長度信息,後面的六個字節可能與空閒內存鏈表的信息有關,在翻譯內存時用來提供必要的信息。這就解答了前面提出的問題,原來C/C++在分配內存時已經記錄了足夠充分的信息用於回收內存,只不過我們平常不關心它罷了。

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