關於malloc原始碼中的bin_at巨集定義的個人見解

tolele發表於2022-03-16

0x01:簡介

      在堆中的記憶體申請和釋放中,為了減少使用系統呼叫函式對記憶體操作,malloc_state(分配區)結構中使用了fastbinsY陣列和bins陣列。當chunk被free後,bins鏈會將這些free chunk組織起來。當下次malloc時,會先對bins鏈中的free chunk進行遍歷,有適合的則使用,無合適的再進行下一步操作。

     在申請和釋放操作時,一般是有一個arena(分配區,其為malloc_state結構型別)。通過巨集定義bin_at(m,i)即可獲得對相應bins鏈進行操作,m為分配區,i為索引,當i=1是為unsorted bin,i=2~63是small bin,i=64~126為large bin。

bin_at可以這樣使用:
p = bin_at(m,1)  //unsorted bin
FD = p -> fd     //FD指向該鏈的第一個free chunk
BK = p -> bk     //BK指向該鏈的最後一個free chunk

 

 

 0x02:個人理解

該巨集定義為這樣子,主要是為了操作方便(可直接fd、bk指向)和在節省空間之間取平衡。既操作方便又不浪費空間。

bin_at(m,i)巨集定義原型:

#define bin_at(m, i) \
  (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2]))                              \
             - offsetof (struct malloc_chunk, fd))
解釋:
1、&((m)->bins[((i)-1)*2]),該式子根據bin的索引i,i為1時,即最開始的bin(unsorted bin)。
獲得bins[0]的地址,乘於2主要是因為fd和bk是一對儲存的。

2、offsetof(struct malloc_chunk,fd):得到fd成員在malloc_chunk結構中的偏移量。在64位系統系統下為16。
把第一步得到地址(令其為pt)轉化為char*型,這樣子減偏移值: pt - offsetof = pt - offsetof*(sizeof(char))。

3、重點:
在第二步下,第一步得到的地址指向往後推移了兩個單元,比如圖中的bin_at(m,1)得到的是bins[0]前兩個單元所在的地址。
然後經過最後的(mbinptr)轉化為malloc_chunk*型別,這樣就可以有->fd、->bk操作。
相當於是糊弄了作業系統,讓作業系統誤以為是個chunk結構。

 

 

 語言表達不夠,畫圖來湊~~

0x03:測試

 1 測試程式碼:
 2 #include<stdio.h>
 3 #include<malloc.h>
 4 
 5 int main()
 6 {
 7     void* p1 = malloc(0x100);
 8     void* f1 = malloc(0x10);   //防止合併
 9     void* p2 = malloc(0x100);
10     void* f2 = malloc(0x10);
11     void* p3 = malloc(0x100);
12     void* f3 = malloc(0x10);
13 
14     sleep(0);  //方便下斷點
15 
16     free(p1);
17     free(p2);
18     free(p3);
19 
20     sleep(0);  //下圖斷在了這裡
21     return 0;
22 }

 

 

 

 可以看出unsorted bin的第一個單元是指向bin鏈的第一個free chunk,另外一個單元指向bin鏈的最後一個free chunk。圖中我已經標出了指向top chunk的那個單元,也有:bin_at(m,1)指向該單元 ,或者更本質一點:bin_at(m,1) = 0x7ffffdd1b78。

 0x04:思考

        在剛開始看這個巨集定義時,一臉懵逼,覺得這個巨集定義是有問題吧,減去16不是超出了範圍了麼?後來繼續分析原始碼時發現了->fd和->bk的操作,陷入了沉思。巧的是,群裡有師傅剛好提到這個問題,所以和該師傅交流了一下,最後得到了一個比較合理的解釋。

       但是令我疑惑的是,為什麼在後面會留兩個空白單元嘞?留在前面不是更恰當麼?bin_at(m,1)指向了bins陣列外面的單元(存top chunk地址的單元),這樣會不會存有遺患呢?有想法的歡迎與我交流^_^,QQ:1623093551。

 


tolele 2022-03-16

相關文章