為什么free()時不需要傳遞大小

malloc()和free()是c中兩個非持怨В基本的函數(shù),但這種最基本的東西往往都是特別復雜的纯续。
malloc和free的原形如下:

void *malloc(unsigned int num_bytes);
void free(void *ptr);

在c的標準中并沒有定義這兩個函數(shù)的具體實現(xiàn)随珠,在我們最常用的gcc中,malloc使用的是ptmalloc的實現(xiàn)猬错,最早由Doug Lea完成窗看,并被Wolfram Gloger改進以支持多線程。
malloc的具體實現(xiàn)過于復雜倦炒,這里就不具體展開了显沈。
總體上說,ptmalloc的內存管理是基于內存池的逢唤,而它的內存來源有兩種:
1 通過brk()獲得
2 通過mmap()匿名映射獲得
這兩種獲得內存的方式分別對應于進程地址空間的不同部分构罗。64位linux進程的默認內存布局如下:


對于其中的Heap區(qū)域,就是我們通常意義上的堆空間智玻,這部分內存將通過brk()獲得遂唧。brk()的原理非常簡單,只涉及指針的上下移動吊奢,也就是只分配虛擬地址空間盖彭,而不分配物理內存,當實際訪問到此內存時页滚,將觸發(fā)page fault異常由操作系統(tǒng)完成物理內存的分配召边。由于操作簡單,所以brk的效率非常高裹驰。
而另一個Memory Mapping Region區(qū)域隧熙,簡稱mmap區(qū)域,將通過操作系統(tǒng)的mmap()函數(shù)獲得幻林。mmap區(qū)域不僅可以提供內存的分配贞盯,還可以映射文件,比如通過mmap打開文件沪饺,或者加載so文件等等躏敢。
mmap函數(shù)的原形如下:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 

其中的flags,在使用mmap分配內存時整葡,設置為MAP_ANONYMOUS件余,也就是匿名映射。當使用mmap()映射內存時,操作系統(tǒng)默認將對這塊內存執(zhí)行清0操作啼器,因此相比于brk旬渠,mmap的效率相對較低。
基于內存池的內存管理端壳,本質上都是把變長的內存分配轉換為定長的內存分配坟漱。因為只有定長,才可以復用更哄。
ptmalloc的內存池結構大致如下:


可以看出芋齿,內存的分配將根據(jù)實際的大小,選擇定長塊成翩。比如請求的內存是23字節(jié)觅捆,那么將分配一塊24字節(jié)的內存,而請求的如果是25字節(jié)麻敌,那么將分配一塊32字節(jié)的內存(對于大于512字節(jié)的數(shù)據(jù)栅炒,統(tǒng)一存儲在large bin中)。具體的分配策略就不展開了术羔。
每一種大小的內存赢赊,都組成了一個一個的隊列,在這些隊列里維護了一個雙向鏈表级历,將所有的小塊內存串聯(lián)起來释移。每一個小塊內存(chunk)的結構如下:


上面的這個結構是一塊在使用中的內存的狀態(tài)。其中的mem部分寥殖,則是返回給用戶的void*指針位置玩讳。而最開始的兩個結構:size of previous chunk,和 size of chunk嚼贡,則用于維護全局內存的鏈表熏纯。
之所以說是全局內存的鏈表,是由于內存分配時是先向系統(tǒng)請求一個比較大的內存塊(64位系統(tǒng)一般為64Mb)粤策,之后從這64Mb內存中切出用戶需要的大小分配給用戶樟澜。而為了維護分配出去的內存塊之間的關系,通過前兩個結構來使所有內存塊構成一個大的鏈表叮盘,當回收內存時秩贰,通過這個全局鏈表,將所有空閑內存組合起來熊户,還給操作系統(tǒng)萍膛,其中有3個標記位:A,M嚷堡,P,P標識前一塊內存是否空閑。
下面的結構就是一塊空閑內存的狀態(tài):

相比于使用中的狀態(tài)蝌戒,空閑部分的內存增加了4個新的結構(Forward pointer to next chunk in list 等串塑,其中fd_nextsize和bk
_nextsize只存在于large bin中),這4個結構用于維護每個定長內存隊列的雙向鏈表結構北苟,這個鏈表的存在主要是為了分配時查找內存時足夠便利桩匪,可以基本上保證分配內存時的平均復雜度維持在O(1)。

在有了前面所有的介紹之后友鼻,可以總體上描述一下malloc和free的基本流程:
當用戶向ptmalloc請求內存時:
1 首先查找定長內存分配池傻昙,如果查找到則返回
2 如果沒有空閑內存可供使用,則向操作系統(tǒng)申請一塊64Mb的內存彩扔,從中切出用戶需要的內存妆档,返回
當用戶調用free釋放內存時:
1 直接將內存放入適當?shù)亩ㄩL內存池隊列
2 如果觸發(fā)了一定的條件,則將所有空閑內存合并虫碉,如果滿足釋放條件贾惦,將內存全部還給操作系統(tǒng)

當然了,上面的描述中省略了太多的細節(jié)敦捧。比如什么時候走brk什么時候走mmap须板, 再比如當請求的內存大于一個闕值時,ptmalloc將會變成一個mmap的簡單封裝兢卵,還有觸發(fā)內存歸還操作系統(tǒng)的條件等等习瑰。
不過已經足夠回答題目中的問題了:因為malloc的時候記錄了大小。
這里還可以得出另一個結論:由于malloc的時候記錄了大量的狀態(tài)秽荤,所以在頻繁使用malloc分配小內存時杰刽,會造成大量的內存浪費。舉例來說王滤,當反復malloc(1)時贺嫂,每一次分配的內存在32字節(jié):包括size of previous chunk,size of chunk雁乡,bk_chunk_pointer第喳,fd_chunk_pointer共4個指針,合計4 * 8 = 32字節(jié)....

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末踱稍,一起剝皮案震驚了整個濱河市曲饱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珠月,老刑警劉巖扩淀,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異啤挎,居然都是意外死亡驻谆,警方通過查閱死者的電腦和手機卵凑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胜臊,“玉大人勺卢,你說我怎么就攤上這事∠蠖裕” “怎么了黑忱?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長勒魔。 經常有香客問我甫煞,道長,這世上最難降的妖魔是什么冠绢? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任抚吠,我火速辦了婚禮,結果婚禮上唐全,老公的妹妹穿的比我還像新娘埃跷。我一直安慰自己,他們只是感情好邮利,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布弥雹。 她就那樣靜靜地躺著,像睡著了一般延届。 火紅的嫁衣襯著肌膚如雪剪勿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天方庭,我揣著相機與錄音厕吉,去河邊找鬼。 笑死械念,一個胖子當著我的面吹牛头朱,可吹牛的內容都是我干的。 我是一名探鬼主播龄减,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼项钮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了希停?” 一聲冷哼從身側響起烁巫,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宠能,沒想到半個月后亚隙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡违崇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年阿弃,在試婚紗的時候發(fā)現(xiàn)自己被綠了淹冰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栈幸。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡须误,死狀恐怖俏险,靈堂內的尸體忽然破棺而出肴楷,到底是詐尸還是另有隱情水由,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布赛蔫,位于F島的核電站砂客,受9級特大地震影響,放射性物質發(fā)生泄漏呵恢。R本人自食惡果不足惜鞠值,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渗钉。 院中可真熱鬧彤恶,春花似錦、人聲如沸鳄橘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘫怜。三九已至术徊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鲸湃,已是汗流浹背赠涮。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暗挑,地道東北人笋除。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像炸裆,于是被迫代替她去往敵國和親垃它。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內容

  • C/C++程序為什么比起其它語言開發(fā)的程序效率要高晒衩,一個很重要的原因就是可以直接操作內存嗤瞎,今天就來講講為什么...
    耐寒閱讀 4,324評論 0 8
  • Linux內存空間簡介 32位Linux平臺下進程虛擬地址空間分布如下圖: Linux提供了如下幾個系統(tǒng)調用,用于...
    90后老碼農閱讀 11,426評論 2 14
  • linux內存尋址 3種地址:虛擬地址听系、物理地址贝奇、邏輯地址物理地址:內存的電路地址,對應內存地址線上的高低電平靠胜,物...
    grimlock44閱讀 1,121評論 0 1
  • 最近開始入坑linux下的堆漏洞成因與利用方式掉瞳,首先從認識堆開始毕源,一步步為自己的學習做一些總結。 0x00 什么是...
    星辰照耀你我閱讀 1,118評論 0 4
  • 昨天是孩子開家長會的時間,盡管我做了很多的心里建設卻依然沒有逃脫心態(tài)的崩裂该镣。 對照老師在PPT上展示出來孩子的種種...
    魚羊姑娘閱讀 387評論 6 4