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)的代碼
有時看到代碼是這么寫的:
這樣有問題嗎 ? 在服務器上長期運行,會引起內(nèi)存泄漏嗎?
寫了個測試程序, 看看這些都是神馬。
程序運行結果:
注意這里多出來的 4字節(jié)
三、總結
這個問題直接導致我們需要在 new [] 一個對象數(shù)組時,需要保存數(shù)組的維度,C++ 的做法是在分配數(shù)組空間時多分配了 4 個字節(jié)的大小,專門保存數(shù)組的大小,
在 delete [] 時就可以取出這個保存的數(shù),就知道了需要調(diào)用析構函數(shù)多少次了。
四、c++對象內(nèi)存分配與釋放
有人提出兩個問題:
1、那個4字節(jié)在 delete [] , 是怎么跳過的。
2、free 是怎么知道自己的長度。
以下寫幾個栗子 看一下:
delete 對象 :
部分匯編碼如下:
delete復雜數(shù)據(jù)類型先調(diào)用析構函數(shù)再調(diào)用operator delete。
c++的內(nèi)存分配
看一下 M$ 編譯器是如何構造和釋放內(nèi)存的
小的總結
內(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é)的呢?
實在不想看了 ,貼一點 關鍵的吧 , New 對象的部分匯編
上面的匯編碼流程大致是:
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é)的。
以上的匯編似乎沒有涉及 4字節(jié)的偏移 , 那看看 vector deleting destructor 這個函數(shù)干了啥
看到 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