事實(shí)上,仔細(xì)看一下free()的函數(shù)原型,也許也會(huì)發(fā)現(xiàn)似乎很神奇,free()函數(shù)非常簡(jiǎn)單,只有一個(gè)參數(shù),只要把指向申請(qǐng)空間的指針傳遞
給free()中的參數(shù)就可以完成釋放工作!這里要追蹤到malloc()的申請(qǐng)問(wèn)題了。申請(qǐng)的時(shí)候?qū)嶋H上占用的內(nèi)存要比申請(qǐng)的大。因?yàn)槌龅目臻g是用來(lái)記錄對(duì)這塊內(nèi)存的管理信息。先看一下在《UNIX環(huán)境高級(jí)編程》中第七章的一段話:
大多數(shù)實(shí)現(xiàn)所分配的存儲(chǔ)空間比所要求的要稍大一些,額外的空間用來(lái)記錄管理信息——分配塊的長(zhǎng)度,指向下一個(gè)分配塊的指針等等。這就意味著如果寫過(guò)一個(gè)已分配區(qū)的尾端,則會(huì)改寫后一塊的管理信息。這種類型的錯(cuò)誤是災(zāi)難性的,但是因?yàn)檫@種錯(cuò)誤不會(huì)很快就暴露出來(lái),所以也就很難發(fā)現(xiàn)。將指向分配塊的指針向后移動(dòng)也可能會(huì)改寫本塊的管理信息。
以上這段話已經(jīng)給了我們一些信息了。malloc()申請(qǐng)的空間實(shí)際我覺(jué)得就是分了兩個(gè)不同性質(zhì)的空間。一個(gè)就是用來(lái)記錄管理信息的空間,另外一個(gè)就是可用空間了。而用來(lái)記錄管理信息的實(shí)際上是一個(gè)結(jié)構(gòu)體。在C語(yǔ)言中,用結(jié)構(gòu)體來(lái)記錄同一個(gè)對(duì)象的不同信息是
天經(jīng)地義的事!下面看看這個(gè)結(jié)構(gòu)體的原型:
程序代碼:
struct mem_control_block ...{
int is_available; //這是一個(gè)標(biāo)記?
int size; //這是實(shí)際空間的大小
};
對(duì)于size,這個(gè)是實(shí)際空間大小。這里其實(shí)我有個(gè)疑問(wèn),is_available是否是一個(gè)標(biāo)記?因?yàn)槲铱戳薴ree()的源代碼之后對(duì)這個(gè)變量感覺(jué)有點(diǎn)納悶(源代碼在下面分析)。這里還請(qǐng)大家指出!
所以,free()就是根據(jù)這個(gè)結(jié)構(gòu)體的信息來(lái)釋放malloc()申請(qǐng)的空間!而結(jié)構(gòu)體的兩個(gè)成員的大小我想應(yīng)該是操作系統(tǒng)的事了。但是這里有一個(gè)問(wèn)題,malloc()申請(qǐng)空間后返回一個(gè)指針應(yīng)該是指向第二種空間,也就是可用空間!不然,如果指向管理信息空間的話,寫入的內(nèi)容和結(jié)構(gòu)體的類型有可能不一致,或者會(huì)把管理信息屏蔽掉,那就沒(méi)法釋放內(nèi)存空間了,所以會(huì)發(fā)生錯(cuò)誤?。ǜ杏X(jué)自己這里說(shuō)的是廢話)
好了!下面看看free()的源代碼,我自己分析了一下,覺(jué)得比起malloc()的源代碼倒是容易簡(jiǎn)單很多。只是有個(gè)疑問(wèn),下面指出!
程序代碼:
void free(void *ptr) ...{
struct mem_control_block *free;
free = ptr - sizeof(struct mem_control_block);
free->is_available = 1;
return;
}
看一下函數(shù)第二句,這句非常重要和關(guān)鍵。其實(shí)這句就是把指向可用空間的指針倒回去,讓它指向管理信息的那塊空間,因?yàn)檫@里是在值上減去了一個(gè)結(jié)構(gòu)體的大?。『竺婺且痪鋐ree->is_available = 1;我有點(diǎn)納悶!我的想法是:這里is_available應(yīng)該只是一個(gè)標(biāo)記而已!因?yàn)閺倪@個(gè)變量的名稱上來(lái)看,is_available 翻譯過(guò)來(lái)就是“是可以用”。不要說(shuō)我土!我覺(jué)得變量名字可以反映一個(gè)變量的作用,特別是嚴(yán)謹(jǐn)?shù)拇a。這是源代碼,所以我覺(jué)得絕對(duì)是嚴(yán)謹(jǐn)?shù)模?!這個(gè)變量的值是1,表明是可以用的空間!只是這里我想了想,如果把它改為0或者是其他值不知道會(huì)發(fā)生什么事?!但是有一點(diǎn)我可以肯定,就是釋放絕對(duì)不會(huì)那么順利進(jìn)行!因?yàn)檫@是一個(gè)標(biāo)記!
當(dāng)然,這里可能還是有人會(huì)有疑問(wèn),為什么這樣就可以釋放呢??我剛才也有這個(gè)疑問(wèn)。后來(lái)我想到,釋放是操作系統(tǒng)的事,那么就free()這個(gè)源代碼來(lái)看,什么也沒(méi)有釋放,對(duì)吧?但是它確實(shí)是確定了管理信息的那塊內(nèi)存的內(nèi)容。所以,free()只是記錄了一些信息,然后告訴操作系統(tǒng)那塊內(nèi)存可以去釋放,具體怎么告訴操作系統(tǒng)的我不清楚,但我覺(jué)得這個(gè)已經(jīng)超出了我這篇文章的討論范圍了。
那么,我之前有個(gè)錯(cuò)誤的認(rèn)識(shí),就是認(rèn)為指向那塊內(nèi)存的指針不管移到那塊內(nèi)存中的哪個(gè)位置都可以釋放那塊內(nèi)存!但是,這是大錯(cuò)特錯(cuò)!釋放是不可以釋放一部分的!首先這點(diǎn)應(yīng)該要明白。而且,從free()的源代碼看,ptr只能指向可用空間的首地址,不然,減去結(jié)構(gòu)體大小之后一定不是指向管理信息空間的首地址。所以,要確保指針指向可用空間的首地址!不信嗎?自己可以寫一個(gè)程序然后移動(dòng)指向可用空間的指針,看程序會(huì)有會(huì)崩!
給free()中的參數(shù)就可以完成釋放工作!這里要追蹤到malloc()的申請(qǐng)問(wèn)題了。申請(qǐng)的時(shí)候?qū)嶋H上占用的內(nèi)存要比申請(qǐng)的大。因?yàn)槌龅目臻g是用來(lái)記錄對(duì)這塊內(nèi)存的管理信息。先看一下在《UNIX環(huán)境高級(jí)編程》中第七章的一段話:
大多數(shù)實(shí)現(xiàn)所分配的存儲(chǔ)空間比所要求的要稍大一些,額外的空間用來(lái)記錄管理信息——分配塊的長(zhǎng)度,指向下一個(gè)分配塊的指針等等。這就意味著如果寫過(guò)一個(gè)已分配區(qū)的尾端,則會(huì)改寫后一塊的管理信息。這種類型的錯(cuò)誤是災(zāi)難性的,但是因?yàn)檫@種錯(cuò)誤不會(huì)很快就暴露出來(lái),所以也就很難發(fā)現(xiàn)。將指向分配塊的指針向后移動(dòng)也可能會(huì)改寫本塊的管理信息。
以上這段話已經(jīng)給了我們一些信息了。malloc()申請(qǐng)的空間實(shí)際我覺(jué)得就是分了兩個(gè)不同性質(zhì)的空間。一個(gè)就是用來(lái)記錄管理信息的空間,另外一個(gè)就是可用空間了。而用來(lái)記錄管理信息的實(shí)際上是一個(gè)結(jié)構(gòu)體。在C語(yǔ)言中,用結(jié)構(gòu)體來(lái)記錄同一個(gè)對(duì)象的不同信息是
天經(jīng)地義的事!下面看看這個(gè)結(jié)構(gòu)體的原型:
程序代碼:
struct mem_control_block ...{
int is_available; //這是一個(gè)標(biāo)記?
int size; //這是實(shí)際空間的大小
};
對(duì)于size,這個(gè)是實(shí)際空間大小。這里其實(shí)我有個(gè)疑問(wèn),is_available是否是一個(gè)標(biāo)記?因?yàn)槲铱戳薴ree()的源代碼之后對(duì)這個(gè)變量感覺(jué)有點(diǎn)納悶(源代碼在下面分析)。這里還請(qǐng)大家指出!
所以,free()就是根據(jù)這個(gè)結(jié)構(gòu)體的信息來(lái)釋放malloc()申請(qǐng)的空間!而結(jié)構(gòu)體的兩個(gè)成員的大小我想應(yīng)該是操作系統(tǒng)的事了。但是這里有一個(gè)問(wèn)題,malloc()申請(qǐng)空間后返回一個(gè)指針應(yīng)該是指向第二種空間,也就是可用空間!不然,如果指向管理信息空間的話,寫入的內(nèi)容和結(jié)構(gòu)體的類型有可能不一致,或者會(huì)把管理信息屏蔽掉,那就沒(méi)法釋放內(nèi)存空間了,所以會(huì)發(fā)生錯(cuò)誤?。ǜ杏X(jué)自己這里說(shuō)的是廢話)
好了!下面看看free()的源代碼,我自己分析了一下,覺(jué)得比起malloc()的源代碼倒是容易簡(jiǎn)單很多。只是有個(gè)疑問(wèn),下面指出!
程序代碼:
void free(void *ptr) ...{
struct mem_control_block *free;
free = ptr - sizeof(struct mem_control_block);
free->is_available = 1;
return;
}
看一下函數(shù)第二句,這句非常重要和關(guān)鍵。其實(shí)這句就是把指向可用空間的指針倒回去,讓它指向管理信息的那塊空間,因?yàn)檫@里是在值上減去了一個(gè)結(jié)構(gòu)體的大?。『竺婺且痪鋐ree->is_available = 1;我有點(diǎn)納悶!我的想法是:這里is_available應(yīng)該只是一個(gè)標(biāo)記而已!因?yàn)閺倪@個(gè)變量的名稱上來(lái)看,is_available 翻譯過(guò)來(lái)就是“是可以用”。不要說(shuō)我土!我覺(jué)得變量名字可以反映一個(gè)變量的作用,特別是嚴(yán)謹(jǐn)?shù)拇a。這是源代碼,所以我覺(jué)得絕對(duì)是嚴(yán)謹(jǐn)?shù)模?!這個(gè)變量的值是1,表明是可以用的空間!只是這里我想了想,如果把它改為0或者是其他值不知道會(huì)發(fā)生什么事?!但是有一點(diǎn)我可以肯定,就是釋放絕對(duì)不會(huì)那么順利進(jìn)行!因?yàn)檫@是一個(gè)標(biāo)記!
當(dāng)然,這里可能還是有人會(huì)有疑問(wèn),為什么這樣就可以釋放呢??我剛才也有這個(gè)疑問(wèn)。后來(lái)我想到,釋放是操作系統(tǒng)的事,那么就free()這個(gè)源代碼來(lái)看,什么也沒(méi)有釋放,對(duì)吧?但是它確實(shí)是確定了管理信息的那塊內(nèi)存的內(nèi)容。所以,free()只是記錄了一些信息,然后告訴操作系統(tǒng)那塊內(nèi)存可以去釋放,具體怎么告訴操作系統(tǒng)的我不清楚,但我覺(jué)得這個(gè)已經(jīng)超出了我這篇文章的討論范圍了。
那么,我之前有個(gè)錯(cuò)誤的認(rèn)識(shí),就是認(rèn)為指向那塊內(nèi)存的指針不管移到那塊內(nèi)存中的哪個(gè)位置都可以釋放那塊內(nèi)存!但是,這是大錯(cuò)特錯(cuò)!釋放是不可以釋放一部分的!首先這點(diǎn)應(yīng)該要明白。而且,從free()的源代碼看,ptr只能指向可用空間的首地址,不然,減去結(jié)構(gòu)體大小之后一定不是指向管理信息空間的首地址。所以,要確保指針指向可用空間的首地址!不信嗎?自己可以寫一個(gè)程序然后移動(dòng)指向可用空間的指針,看程序會(huì)有會(huì)崩!

