前言
上节《glibc内存管理ptmalloc》我们讲了fastbin/unsortedbin/smallbin, 有意避开了largebin, 因为largebin稍微复杂一点点,需要单独一节讲解。
largebin的特点
- chunk size 大于等于1024字节
- largebin共有63个链表
- largebin每个链表中的chunk size不固定
- largebin中的链表不仅使用fd/bk串起来,还用fd_nextsize、bk_nextsize串起来,目的是跳跃式的寻找下个size大小的chunk. 按size大小排序chunk,大的在前,小的在后。
任意给出一个大于等于1024的size,可根据下面这个宏查在哪个链表中
// XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well.
#define largebin_index_64(sz) \
(((((unsigned long)(sz)) >> 6) <= 48) ? 48 + (((unsigned long)(sz)) >> 6) : ((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9) \
: ((((unsigned long)(sz)) >> 12) <= 10) ? 110 + (((unsigned long)(sz)) >> 12) \
: ((((unsigned long)(sz)) >> 15) <= 4) ? 119 + (((unsigned long)(sz)) >> 15) \
: ((((unsigned long)(sz)) >> 18) <= 2) ? 124 + (((unsigned long)(sz)) >> 18) \
: 126)
我制作了一个表格,更加清晰明了。
例子
目的:设计一个例子,查看largebin链表中的内容,了解fd/bk_nextsize的作用,并验证size与index的映射关系。
int main(int argc, char* argv[])
{
void* arr[10];
arr[0] = malloc(20);
arr[1] = malloc(1024+10);
arr[2] = malloc(20);
arr[3] = malloc(1024+10);
arr[4] = malloc(20);
arr[5] = malloc(1024+10);
arr[6] = malloc(20);
arr[7] = malloc(1024+26);
arr[8] = malloc(20);
arr[9] = malloc(1024+26);
malloc(20);
for(int i=1;i<10;i+=2) free(arr[i]); //free to unsortedbin
void* p = malloc(20); //move items in unsortedbin to largebins
printf("getchar\n");
getchar();
return 0;
}
调试到getchar, 1024+10+16(自重)和1024+26+16都属于下标为64-1的链表
(gdb) p main_arena.bins[63*2]
$4 = (mchunkptr) 0x602ce0
(gdb) p main_arena.bins[63*2+1]
$5 = (mchunkptr) 0x602460
(gdb) p *(mchunkptr)0x602ce0 #arr[7]
$6 = {prev_size = 0, size = 1073, fd = 0x603130, bk = 0x7ffff7dd7a88 <main_arena+1096>, fd_nextsize = 0x602020,
bk_nextsize = 0x602020}
(gdb) p *(mchunkptr)0x603130 #arr[9]
$7 = {prev_size = 0, size = 1073, fd = 0x602020, bk = 0x602ce0, fd_nextsize = 0x0, bk_nextsize = 0x0}
(gdb) p *(mchunkptr)0x602020 #arr[1]
$8 = {prev_size = 0, size = 1057, fd = 0x6028a0, bk = 0x603130, fd_nextsize = 0x602ce0, bk_nextsize = 0x602ce0}
(gdb) p *(mchunkptr)0x6028a0 #arr[5]
$9 = {prev_size = 0, size = 1057, fd = 0x602460, bk = 0x602020, fd_nextsize = 0x0, bk_nextsize = 0x0}
(gdb) p *(mchunkptr)0x602460 #arr[3]
$10 = {prev_size = 0, size = 1057, fd = 0x7ffff7dd7a88 <main_arena+1096>, bk = 0x6028a0, fd_nextsize = 0x0,
bk_nextsize = 0x0}