/*
Place the chunk in unsorted chunk list. Chunks are not placed into regular bins until after they have been given one chance to be used in malloc.
*/
bck = unsorted_chunks(av); #获取unsorted bin的第一个chunk
/*
/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
#define unsorted_chunks(M) (bin_at (M, 1))
*/
fwd = bck->fd;
……
p->fd = fwd;
p->bk = bck;
if (!in_smallbin_range(size))
{
p->fd_nextsize = NULL;
p->bk_nextsize = NULL;
}
bck->fd = p;
fwd->bk = p;
set_head(p, size | PREV_INUSE); #设置当前chunk的size,并将前一个chunk标记为已使用
set_foot(p, size); #将后一个chunk的prev_size设置为当前chunk的size
/*
/* Set size/use field */
#define set_head(p, s) ((p)->size = (s))
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->prev_size = (s))
*/
/* Lightweight tests: check whether the block is already the top block*/
//判断当前free的chunk是否是top chunk,因为top chunk本身就是一个空闲的chunk,如果是top chunk,造成 double free
if (__glibc_unlikely (p == av->top)){
errstr = "double free or corruption (top)";
goto errout;
}
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)//不是通过mmap分配的,是通过sbrk()分配的
&& (char *) nextchunk //下一个chunk的地址如果已经超过了top chunk的结束地址,报错
>= ((char *) av->top + chunksize(av->top)), 0)){
errstr = "double free or corruption (out)";
goto errout;
}
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk))){//如果下一个chunk没有标示将要释放的这个chunk 的p位为0,说明chunk 可能被double free
errstr = "double free or corruption (!prev)";
goto errout;
}
F = p -> fd; #F = &fake_chunk - 12
B = p -> bk; #B = &fake_chunk- 8
if (F -> bk == p && B -> fd == p){
F -> bk = B; #即buf[0] = B = &fake_chunk - 8
B -> fd = F; #即buf[0] = F = &fake_chunk -12
}