想必大家都知道C語言中動態(tài)開辟內(nèi)存之后,必須要釋放內(nèi)存,來防止內(nèi)存泄露。也就是malloc之后,必須要free。正所謂”有借有還,再借不難”, 不少同學(xué)會問為什么釋放指針后,指向這塊內(nèi)存的指針的值不變呢,我們今天為大家揭秘。
首先,我們用malloc開辟一個(gè)內(nèi)存,用strcpy拷貝一串字符串,然后釋放掉,通過斷點(diǎn)調(diào)試進(jìn)行觀察!
下圖可以看到,在VC6編譯環(huán)境下,觀察指針p的指針?biāo)赶虻膬?nèi)容已經(jīng)被strcpy后改變
下一步free函數(shù),我們選擇F11單步介入觀察,幸運(yùn)的是在VC6中可以看到源代碼,如下圖,會進(jìn)入到DBGHEAP.c文件中,會調(diào)用_free_dbg函數(shù),繼續(xù)F11介入觀察代碼
多次單步之后,我們可以看到一個(gè)memset函數(shù),那么F10執(zhí)行這memset,觀察P指向的內(nèi)容,果然不出我們所料:
0x00970e38處的內(nèi)容已經(jīng)被0xDD覆蓋,如下圖紅色字部分。
這里重點(diǎn)觀察了,這個(gè)memset函數(shù)我們應(yīng)該很熟悉,第二個(gè)參數(shù)即為要重置的內(nèi)容,這里我們可以轉(zhuǎn)到定義 處,或者搜索第二個(gè)參數(shù)_bDeadLandFill,可以看到有如下定義, 為0xDD
怎么樣,大家看到這里應(yīng)該明白了吧!
我們這里是VC6編譯器下的環(huán)境,也有部分同學(xué)反映free之后內(nèi)容并未消失,這里我們分析可能是部分編譯器free函數(shù)實(shí)現(xiàn)原理不同,歡迎大家自行嘗試,并與我們交流。
而關(guān)于free之后,p的之后為何沒有改變,仍然還是這個(gè)原先堆空間的這個(gè)地址,原因在于free函數(shù)僅僅是將malloc申請的內(nèi)存釋放回去,所謂的釋放也就是告訴編譯器,這塊內(nèi)存已經(jīng)使用完畢,可以收回了。但指針?biāo)赶虻膬?nèi)存值,并不會發(fā)生改變。就可以比方說,你租了一套房子,到期后,房子收回歸還房東,而此時(shí)你可能還拿著房子的鑰匙,這個(gè)時(shí)候你雖然可以繼續(xù)訪問這個(gè)房子(內(nèi)存),但已經(jīng)不屬于你,是非法的。也可能有新的租客入駐更改房子的內(nèi)置,也可能還是這個(gè)樣子。取決于不同的房東(編譯器)和租客(內(nèi)容)。
這就是free釋放內(nèi)存后,指針內(nèi)地址仍然存在,但有時(shí)還可以訪問,有時(shí)候訪問輸出亂碼或輸出其他值的原因。
怎么樣,大家明白了嗎?
有任何問題,或新的發(fā)現(xiàn),歡迎聯(lián)系我們!
C語言研究中心(www.sztianhecheng.cn)