我正在考虑使用显式空闲列表实现分配器,并想知道为什么很多人实现 48 字节作为初始大小。
但大多数人使用 48 而不是 24
#define PACK(size, alloc) ((size) | (alloc))
#define PUT(p, val) (*(size_t *)(p) = (val))
#define WSIZE 4
#define DSIZE 8
#define CHUNKSIZE (1<<12)
#define OVERHEAD 24
static char *heap_listp; /* pointer to first block */
static char *mem_brk; /* pointer to last byte of heap plus 1 */
void *mem_sbrk(int incr){
char *old_brk = mem_brk;
mem_brk +=incr;
return (void *)old_brk;
}
int mm_init(void)
{
if((heap_listp = mem_sbrk(48) == NULL){ //Return error if unable to get heap space
return -1;
}
PUT(heap_listp, 0);
//Put the Padding at the start of heap
PUT(heap_listp + WSIZE, PACK(OVERHEAD, 1));
//Put the header block of the prologue
PUT(heap_listp + DSIZE, 0);
//Put the previous pointer
PUT(heap_listp + DSIZE + WSIZE, 0);
//Put the next pointer
PUT(heap_listp + OVERHEAD, PACK(OVERHEAD, 1));
//Put the footer block of the prologue
PUT(heap_listp + WSIZE + OVERHEAD, PACK(0, 1));
//Put the header block of the epilogue
if(extend_heap(CHUNKSIZE / WSIZE) == NULL){ //Return error if unable to extend heap space
return -1;
}
return 0;
}
我认为我们有 6 个单词(填充、序言标题 block 、序言页脚 block 、前一个指针、下一个指针和尾声标题 block ) 所以我认为我们需要这样声明
if((heap_listp = mem_sbrk(24)) == NULL)
请随时指出我遗漏的内容。
最佳答案
PUT(heap_listp, 0); //ofset 0
PUT(heap_listp + WSIZE, PACK(OVERHEAD, 1)); //offset 4 - appears to contain a length (of OVERHEAD bytes)
PUT(heap_listp + DSIZE, 0); //offset 8
PUT(heap_listp + DSIZE + WSIZE, 0); //offset 8 + 4 = 12
PUT(heap_listp + OVERHEAD, PACK(OVERHEAD, 1)); // offset 24 - another length of OVERHEAD bytes
PUT(heap_listp + WSIZE + OVERHEAD, PACK(0, 1)); //offset 24 + 4
显然,当您写入字节 31 时,sbrk 需要大于 24
所以看起来初始设置由 2 个 block 组成,两个 block 都是 OVERHEAD 字节长。
对 sbrk 使用 2 * OVERHEAD 会更清楚。使用结构体作为内存区域头也是如此。
关于c - 为什么使用显式空闲列表的分配器需要初始堆大小为 48 字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56273178/