3. 下面我們來看看上面提到的4位元組是幹什麼用的。
int main()
執行結果:
adress after malloc: 0x804a008; size: 104
a::a()
...
adress after new = 0x804a00c
number of a at 0x804a008 = 100
size of a at 0x804a004 = 113
a::~a()
...
adress before free: 0x804a008
從上面的執行結果可以看出,那個被隱藏起來的四位元組放的是陣列元素的個數(number of a at 0x804a008 = 100)。當使用new的時候,new會多分配4個位元組,用來存放陣列的個數,然後把malloc返回的位址+4給使用者使用。而在free的時候,free會把得到的位址-4,得到記憶體中物件的個數,然後把這個位址交於free釋放。如果我們把這個值修改了如 *((int*)a-1) = 50。我們就會發現,上面的程式呼叫了100次建構函式,但是只呼叫了50次析構函式,因為delete以為只有50個陣列元素。
其實malloc自身也隱匿了一些記憶體空間用於自身管理,如malloc返回的位址-4,可以看到malloc分配的空間大小。如果我們把這個值修改了,如:*((int*)a-2) = 0, 程式也會出錯。關於malloc這裡就不多說了,可以看看相關的資料或者linux版上我寫的帖子。
4. 關於內建型別和沒有析構函式的類型別,無論是delete, delete都不會出錯。
class a
// ~a()
}; int main()
執行結果:
adress after malloc: 0x804a008; size: 1
a::a()
adress after new = 0x804a008
adress before free: 0x804a008
可以看出new 返回的位址就是malloc的位址,同理,free傳遞給free的位址也一樣。所以free的時候不會有問題。編譯器在遇到沒有析構函式的類的時候,就認為物件中沒有需要額外釋放的記憶體和處理的資料。所以在既不影響程式正確執行有沒有記憶體洩漏的情況下,直接釋放物件所占用的記憶體就好了。
注意:這完全是編譯器優化的結果,並不能保證程式在所有環境下都能正確執行。
以上所有程式用gcc (gcc) 4.1.0編譯
小結:
1. 無論什麼型別,用new分配的用delet釋放,用new分配的用delete釋放。
2. new和delete的時候會使用隱藏的記憶體來記錄一些陣列資訊,如陣列元素個數。這造成了錯誤的使用了delete或delete的時候,會造成程式錯誤。
3. 對於內建型別和沒有析構函式的類型別,編譯器可能對其進行了優化,造成delete和delete都不會出錯,或者記憶體洩漏。但這是不符合標準,且依賴於具體實現的。
pthread 08.09.13
關於delete 和delete的區別
自己也有和lz同樣的疑惑,於c 屆還是小白一枚啊。問題 看高質量c 程式設計的時候有個地方沒看懂,就是在string的析構函式中釋放m data時用delete m data,但後面跟著有個注釋 由於m data 是內部資料型別,也可以寫成 delete m data delete m data不是...
關於delete和delete 的區別
在c 動態記憶體分配中我們常用到new和delete兩種操作,new用來申請記憶體,delete用來釋放記憶體。那麼問題來了,我們應該用delete來釋放記憶體還是用delete來釋放記憶體呢?為了得到答案我做了一下實驗。注 一下實驗在使用delete和delete得到的結果是一樣的,不重複po圖 ...
delete和delete 的區別
剛才在寫一段例子程式的時候,發現對於乙個指標型別的陣列t p,delete p和delete p的效果一樣。看了一下c primer和c programming language都沒有找到解釋,於是在網路上搜尋一下,發現了很好的解釋。整理一下 c 告訴我們在 用 new 分配的單個物件的記憶體空間的...