unlink_chunk
/* Take a chunk off a bin list. */
static void
unlink_chunk(mstate av, mchunkptr p)
{
// 安全检查:如果当前chunk的大小不等于next chunk的prev_size,说明被篡改了数据,报错
if (chunksize(p) != prev_size(next_chunk(p)))
malloc_printerr("corrupted size vs. prev_size");
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
// 安全检查:如果当前chunk的fd的bk不等于当前chunk,或者bk的fd不等于当前chunk,说明双向链表链接出错,报错
if (__builtin_expect(fd->bk != p || bk->fd != p, 0))
malloc_printerr("corrupted double-linked list");
// 断链操作
fd->bk = bk;
bk->fd = fd;
// 如果是large chunk
// 如果不是smallbin,且fd_nextsize不为空,说明是large chunk
if (!in_smallbin_range(chunksize_nomask(p)) && p->fd_nextsize != NULL)
{
// 安全检查:largebin的第二条双链完整性检查
// 安全检查:如果fd_nextsize的bk_nextsize不等于p,或者bk_nextsize的fd_nextsize不等于p,说明双向链表链接出错,报错
if (p->fd_nextsize->bk_nextsize != p || p->bk_nextsize->fd_nextsize != p)
malloc_printerr("corrupted double-linked list (not small)");
// 如果存在其他大小范围的large chunk
if (fd->fd_nextsize == NULL)
{
// 如果其他大小的large chunk是自己,就设置为自己
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
{
// nextsize链表断链
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;
}
}
}
双链表断链流程:
- 安全检查:下一个chunk的prev_size和当前size是否匹配,不匹配就报错
- 安全检查:链表完整性检查,
**p->fd->bk**
和**p->bk->fd**
是否都指向**p**
,不是就报错 - 检查通过之后,
fd
和bk
断链 - 如果是large chunk,则存在另一条双链表
- 安全检查:对另一个双链表进行链表完整性检查
- 检查通过之后,
fd_nextsize
和bk_nextsize
断链