unlink() 是一个宏,用于将某一个空闲 chunk 从其所处的 bin 中脱链。
在 malloc_consolidate() 函数中将 fastbin 中的空闲 chunk 整理到 unsorted_bin,在 malloc() 函数中用于将 unsorted_bin 中的空闲 chunk 整理到 smallbin 或者 largebin,以及在 malloc() 中获得堆空间时,均有可能调用 unlink() 宏。
#define unlink(AV, P, BK, FD) { FD = P->fd; BK = P->bk; if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) malloc_printerr (check_action, "corrupted double-linked list", P, AV); else { FD->bk = BK; BK->fd = FD; if (!in_smallbin_range (P->size) && __builtin_expect (P->fd_nextsize != NULL, 0)) { if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) malloc_printerr (check_action, "corrupted double-linked list (not small)", P, AV); if (FD->fd_nextsize == NULL) { if (P->fd_nextsize == P) FD->fd_nextsize = FD->bk_nextsize = FD; else { FD->fd_nextsize = P->fd_nextsize; FD->bk_nextsize = P->bk_nextsize; P->fd_nextsize->bk_nextsize = FD; P->bk_nextsize->fd_nextsize = FD; } } else { P->fd_nextsize->bk_nextsize = P->bk_nextsize; P->bk_nextsize->fd_nextsize = P->fd_nextsize; } } } }
|
参数P为待脱链的chunk, BK是前向指针, FD是后向指针
FD保存P chunk的前一个空闲chunk, BK保存后一个空闲chunk
然后是一个检查
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
|
即 判断前一个空闲chunk的后向指针和后一个空闲chunk的前向指针是否指向P
因为fastbins是单链表结构, 所以unlink只能是从smallbins和largebins来脱离
判断成立的话, 会把这个chunk解下来
贴一张ctf wiki的图
接着判断:
if (!in_smallbin_range (P->size) && __builtin_expect (P->fd_nextsize != NULL, 0))
|
即 判断P chunk的size是否在small bin的范围内, 并且判断前一个chunk的size是否为空
#define NBINS 128 #define NSMALLBINS 64 #define SMALLBIN_WIDTH MALLOC_ALIGNMENT #define SMALLBIN_CORRECTION (MALLOC_ALIGNMENT > 2 * SIZE_SZ) #define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \ ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
|
large bin 结构图:
small bin 结构图: