WeTest 導讀

c++ 是公司開發(fā)最常用的語言之一, 那New和Delete 這兩個函數(shù)是所有開發(fā)者即愛又恨的函數(shù)。由new 和delete引發(fā)的bug , coredump , 讓多少程序員加了多少班。


 

一、遇到的問題

C++ 中,你也許經(jīng)常使用 new 和 delete 來動態(tài)申請和

● 釋放內(nèi)存,但你可曾想過以下問題呢?

● new 和 delete 是函數(shù)嗎?

● new [] 和 delete [] 又是什么?什么時候用它們?

● 你知道 operator new 和 operator delete 嗎?

 

為什么 new [] 出來的數(shù)組有時可以用 delete 釋放有時又不行?

 

二、發(fā)現(xiàn)的代碼 

有時看到代碼是這么寫的: 

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

這樣有問題嗎 ?    在服務器上長期運行,會引起內(nèi)存泄漏嗎? 

 

寫了個測試程序, 看看這些都是神馬。 

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

程序運行結果:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

注意這里多出來的 4字節(jié)

 

三、總結

 這個問題直接導致我們需要在 new [] 一個對象數(shù)組時,需要保存數(shù)組的維度,C++ 的做法是在分配數(shù)組空間時多分配了 4 個字節(jié)的大小,專門保存數(shù)組的大小,

在 delete [] 時就可以取出這個保存的數(shù),就知道了需要調(diào)用析構函數(shù)多少次了。

 iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

 

四、c++對象內(nèi)存分配與釋放

 有人提出兩個問題:

       1、那個4字節(jié)在 delete [] , 是怎么跳過的。

       2、free 是怎么知道自己的長度。

 

  以下寫幾個栗子 看一下:

 

delete 對象  :

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

 

部分匯編碼如下:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

delete復雜數(shù)據(jù)類型先調(diào)用析構函數(shù)再調(diào)用operator delete。

 

c++的內(nèi)存分配    

看一下 M$ 編譯器是如何構造和釋放內(nèi)存的 

 iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

小的總結 

內(nèi)存分配一般有兩種方式: 
1 非入侵式,內(nèi)存分配器自行先申請內(nèi)存(和棧配合使用),用作記錄用戶層的申請記錄(地址,大小)。 用戶釋放空間時會查找該表,除了知道釋放空間大小外還能判斷該指針是合法。


2 入侵式,例如用戶要申請1byte的內(nèi)存,而內(nèi)存分配器會分配5byte的空間(32位),前面4byte用于申請的大小。釋放內(nèi)存時會先向前偏移4個byte找到申請大小,再進行釋放。

兩種方法各有優(yōu)缺點,第一種安全,但慢。第二種快但對程序員的指針控制能力要求更高,稍有不慎越界了會對空間信息做成破壞。


絕大多數(shù)的分配器會采用第一種方式實現(xiàn),而操作系統(tǒng)級的分配器采用了虛擬等方式,可能要記錄更多信息。

 

五、最后分析自定義數(shù)組類型 

那么數(shù)組的分配和釋放是 怎么自動的 增加 4 字節(jié) 和 減 4字節(jié)的呢?

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

實在不想看了 ,貼一點 關鍵的吧 , New 對象的部分匯編

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

 

上面的匯編碼流程大致是:

1、調(diào)用operator new分配堆空間

2、調(diào)用構造代理函數(shù)構造堆對象,在調(diào)用構造代理函數(shù)時,通過壓棧,像其傳遞了5個參數(shù),分別是 a)第一個堆對象首地址 b)堆對象大小c)堆對象個數(shù) d)構造函數(shù)地址 e)析構函數(shù)地址

3、傳回第一個堆對象首地址,而不是申請到的堆空間首地址

 

析構的部分代碼

看看析構函數(shù)是如何自動偏移4字節(jié)的。 

 iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

 

 以上的匯編似乎沒有涉及 4字節(jié)的偏移 , 那看看  vector deleting destructor 這個函數(shù)干了啥

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

 

看到  operator delete[] (0341244h) 這個函數(shù)了 , 前面將 對象首地址 -4  ,然后釋放內(nèi)存, 現(xiàn)在知道為啥 析構偏移4字節(jié)了吧 

 


 關于騰訊WeTest (wetest.qq.com)

騰訊WeTest是騰訊游戲官方推出的一站式游戲測試平臺,用十年騰訊游戲測試經(jīng)驗幫助廣大開發(fā)者對游戲開發(fā)全生命周期進行質(zhì)量保障。騰訊WeTest提供:適配兼容測試;云端真機調(diào)試;安全測試;耗電量測試;服務器性能測試;輿情分析等服務。

點擊地址:http://wetest.qq.com/立即體驗!

http://www.cnblogs.com/wetest/p/7133525.html