Unlink宏的实现机制

unlink() 是一个宏,用于将某一个空闲 chunk 从其所处的 bin 中脱链。

在 malloc_consolidate() 函数中将 fastbin 中的空闲 chunk 整理到 unsorted_bin,在 malloc() 函数中用于将 unsorted_bin 中的空闲 chunk 整理到 smallbin 或者 largebin,以及在 malloc() 中获得堆空间时,均有可能调用 unlink() 宏。

/* Take a chunk off a bin list */
#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->fd;
BK = P->bk;

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 //16 in i386
#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 结构图: