contributed by < Korin777
>
pool_malloc
透過 get_loc_to_place
從 memory pool 的 free block 中配置記憶體給使用者
size + header_size
確保釋放時有足夠的空間存放 metadatapool_free
釋放配置的記憶體
get_loc_to_free
找出可能可以 merge 的 free block,因為 free block 的 list 根據 address 從低到高串聯,所以我們只要根據目前釋放的記憶體位置往前或往後找即可測試程式時可以發現如果將 memory pool 的記憶體配置完後,在去釋放這些記憶體,然後再去配置記憶體時會無法獲得可用的記憶體空間,以下為實作上可改進的地方
pool_malloc
pool_free_space
current
_size + word_size
的空間,我認為應該要配置_size + header_size
的空間,因為當這個 block 釋放為 free block 時,假設我們 _size
只配置了 8 bytes , In-use block 就只有 16 bytes 而放不下 metadata , 這時 prev
block pointer 會動到別的 block 的記憶體pool_free
next
或 prev
是否為 NULLget_loc_to_free
tmp_pt
應為 current
的值而非地址,若是後者(即 ¤t
) 此時 tmp_block->prev
會相當於 ((block_t *)¤t)->prev
但我們應該是要 current->prev
get_loc_to_place
free_block
,我們就能把整個 free_block
的記憶體配置出去metadata_t
: 紀錄配置的 memroy block 的資訊
size
: 配置的記憶體大小free
: memroy block 是否被釋放,可用來偵測 double free*next
、*prev
: 連接前後相鄰的 memory blockrbnode_t
: 用來放被釋放的 memroy block , 相同大小的 memory block 會放在同一個 node
size
、free
、*next
、*prev
: node 的 metadatakey
: 放在這個 node 的 memory block 大小**tab_values
: 放 memory block ,預設可以放 256 個,透過 resize_tab_values
增加size_tab
: memory block 可放的總數n_active
: 已放的 memory block 數量color
: node 的顏色*left
、*right
: node 的 childmalloc_t
: 可用的記憶體空間
*root_rbtree
: 用來放被釋放 memroy block 的紅黑樹根節點last_node
: 最新被配置的 memory block*end_in_page
: 目前配置到的記憶體地址,也就是下一次配置記憶體會從這裡開始*first_block
: 最一開始可以使用到的記憶體地址,也就是可用的記憶體最低地址page_size
: 一個 page 的大小,在我的電腦上為 4096 bytesmutex
: 確保只有一個執行續能配置及釋放記憶體的 lockpage_remaining
: 尚未被配置的記憶體空間大小free
metadata_t->free
來看是否合法,再來會用 metadata_t->free
偵測 double freetry_fusion
藉由 metadata_t->prev
、metadata_t->next
、metadata_t->free
來合併相鄰的 free block ,被合併的 block 會從該 rbnode_t
中移除,若移除後 rbnode_t
沒任何 memory block 就將該 rbnode_t
從紅黑樹中移除change_break
來更新 malloc_t
, 若 malloc_t->page_remaining
大於一個 page 就可以透過 brk
來真正釋放我們用 sbrk
配置的記憶體rbnode_t
中 , 若不存在該 memory block 大小 的 rbnode_t
, 就插入新的 rbnode_t
到紅黑樹中, malloc
會透過紅黑樹來使用已配置但現為 free block 的記憶體malloc
ALIGN_BYTES
讓配置的記憶體位置以 16-bytes 對齊(64-bits 系統下)search_freed_block
去紅黑數找已配置但現為 free block 的記憶體,來重用記憶體空間,因為紅黑數為二元搜尋樹,可以發現 find_best
透過這個性質來找出不小於所需 size 的 rbnode_t
來達到 best-fit 的策略
rbnode_t
,就透過 split_block
就將其中一個 free block 移除,因為 free block 空間可能遠高於所需的空間,所以當 free block 剩餘的空間扣掉所需的空間後,仍能放 maclloc
所配置的最小記憶體 SIZE_DEFAULT_BLOCK + META_SIZE
,就將它分割成兩塊,一塊給使用者使用 (in-use block) 而另一塊會重新插入紅黑樹中 (free block)在程式碼中 split_block 要分割的判斷是 node->size > size + sizeof(size_t) && node->size - size > sizeof(rbnode_t) + SIZE_DEFAULT_BLOCK 跟我的想法不同,我認為剩餘的空間扣掉所需的空間後只要不小於最小能配置的記憶體空間,分割出來的 free block 就有機會被重用
rbnode_t
, 就透過 get_heap
來配置記憶體空間
sbrk
來真正配置不小於 size 的 n 倍 pagesize 空間end_in_page
配置新的 in-use block 並與前一個 block 相連,在更新 malloc_t
GET_PAYLOAD
回傳使用者實際能使用的記憶體地址