(1.1)#malloc與free之間的協(xié)議測試
g由malloc函數(shù)分配的堆內(nèi)存使用free函數(shù)釋放歸屬權(quán)的時(shí)候,在free函數(shù)中是不必提供一個參數(shù)入口來指明所需釋放的字節(jié)大小的。這是由于malloc與free這兩個對子之間存在著一些協(xié)議的規(guī)范使得free函數(shù)可以依照協(xié)議按圖索驥,找到需要釋放由malloc函數(shù)申請的堆內(nèi)存大小信息。
而這個協(xié)議就是,malloc函數(shù)在分配堆內(nèi)存并把一個首地址遞交返回時(shí),在首地址的前八個字節(jié)的上存儲了malloc函數(shù)申請堆內(nèi)存的大小。free函數(shù)讀取執(zhí)行時(shí)先讀取malloc申請返回的首地址的前八字節(jié)就能夠?qū)崿F(xiàn)不需要額外從其函數(shù)窗口得知內(nèi)存范圍的前提下來處理用戶申請堆內(nèi)存的釋放。
測試的方法可以通過申請一段由pfirst指針指向首地址的堆內(nèi)存,然后再申請下一段由pnext指針指向首地址相鄰一段堆內(nèi)存。下一段堆內(nèi)存的首地址pnext與pfirst存儲的首地址的代數(shù)差(遞增的堆)就是malloc函數(shù)分配在pfitst指向的堆的內(nèi)存容量V。通過打印pfirst指針指向的前八個字節(jié)(記為X)來比對V與X的相關(guān)程度就可以驗(yàn)證上述協(xié)議是否真確,程序設(shè)計(jì)的思路就是分別打印出V與X來進(jìn)行觀測:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
?
#define oneByte_length "%hhd "
?
void Test()
{
?????? uint8_t* pfirst=malloc(20);
?????? uint8_t* pnext=malloc(1);
?????? printf("分配到歸屬pfirst管理的內(nèi)存有%lu個\n",((uint64_t)pnext-(uint64_t)pfirst));
?????? //嘗試輸出pfirst的前8個字節(jié)
?????? for(int shift=1;shift<=8;shift++)
?????? {
?????? ?????? if(shift==1)
???????????????????? printf("前8個字節(jié)逐個輸出為:");
????????????? printf(oneByte_length,*(pfirst-shift));
?????? }
?????? free(pfirst);
?????? free(pnext);
}
?
void main()
{
?????? Test();
}
其執(zhí)行結(jié)果為:

可見,V與X相差1,而測試分配其他數(shù)值時(shí)比如分配malloc等于60時(shí),需要的容量開銷V與X也是還是相差了1:

V和X一定是相關(guān)的,而至于為什么總是相差1,就現(xiàn)在掌握的信息來說還不得而知。不過可以反向推導(dǎo)利用的時(shí),如果利用pfirst的指向去故意改變X的數(shù)值,那么當(dāng)執(zhí)行free(pfirst)的時(shí)候,必定會出現(xiàn)異常。就像這樣利用下面的程序故意地去破環(huán)malloc與free的協(xié)議:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
?
#define oneByte_length "%hhd "
?
void Test()
{
?????? uint8_t* pfirst=malloc(20);
?????? uint8_t* pnext=malloc(1);
?????? *(pnext)=20;
?????? printf("分配到歸屬pfirst管理的內(nèi)存有%lu個\n",((uint64_t)pnext-(uint64_t)pfirst));
?????? //嘗試輸出pfirst的前10個字節(jié)
?????? for(int shift=1;shift<=8;shift++)
?????? {
????????????? if(shift==8)
???????????????????? *(pfirst-shift)=50;
???????????????????? if(shift==1)
??????????????????????????? printf("前8個字節(jié)逐個輸出為:");
???????????????????? printf(oneByte_length,*(pfirst-shift));
?????? }
?????? free(pfirst);
?????? free(pnext);
//??? printf(oneByte_length,*(pnext));
}
?
void main()
{
?????? Test();
}
結(jié)果是系統(tǒng)檢查到報(bào)錯無疑,

(1.1)#malloc與free之間的協(xié)議測試的評論 (共 條)
