问题描述
最近我一直在研究glibc malloc实现的内部。但是,对于bin索引,我似乎无法理解一件事。因此,在malloc_state结构中,我们有以下声明,为了简洁起见,它们的格式很简单:
struct malloc_state
{
/*
.
.
Some declarations
.
.
*/
/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;
/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];
/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];
/*
.
.
Some more declarations
.
.
*/
};
现在我的问题是关于此结构中bins数组的声明。 bins数组声明如下:
mchunkptr bins[NBINS * 2 - 2];
据我所知,使用bin_at宏定义了指向垃圾箱的指针,如下所示:
typedef struct malloc_chunk *mbinptr;
/* addressing -- note that bin_at(0) does not exist */
#define bin_at(m,i) \
(mbinptr) (((char *) &((m)->bins[((i) - 1) * 2])) \
- offsetof (struct malloc_chunk,fd))
现在,我的问题如下。为什么bins数组中保留的bin数量大约是两倍?我了解到,由于调用free而导致为未排序的块保留了一个bin,对于已排序大小的空闲块有NBINS个bin数量。但是,我不了解其余垃圾箱的用途。
我怀疑这是有原因的。但是,从源代码来看,这对我来说还不清楚。如果你们中的任何人有一些指针或说明为什么这样做的文档,将不胜感激!
提前谢谢!
解决方法
由于bin是双向链接的列表,所以每个bin头都包含两个指针,而不是一个:第一个指针指向列表的开头,第二个指针指向结尾的指针。这就是为什么指针是箱的两倍的原因。 (请注意,未使用箱号0,因此箱数实际上是NBINS - 1
。)
在双向链接列表实现中很常见,列表实际上是循环的;标头可以视为链接条目。这样就避免了在添加元素之前检查垃圾箱是否存在的必要。 (在空容器中,第一个和最后一个点都指向容器标题本身。)但是,fd
中的前向(bk
)和后向(malloc_chunk
)指针不在块的开始。为了将bin数组中的一对指针视为一个块条目,该对指针的地址需要反向偏移fd
中的malloc_chunk
指针的偏移量。>
图可能会有所帮助。垃圾箱中有两个大块的样子如下:
Bins Array Chunk 0 Chunk 1
+--> XXXXXXXXXX <-\ /--> +--------+ <-\ /--> +--------+ <-----+
| XXXXXXXXXX \ / | p_sz | \ / | p_sz | |
| XXXXXXXXXX \ / +--------+ \ / +--------+ |
| XXXXXXXXXX X | sz | X | sz | |
| +--------+ / \ +--------+ / \ +--------+ |
| | [2i-2] | -->/ \ | fd | -->/ \ | fd | ->+ |
| +--------+ \ +--------+ \ +--------+ | |
| | [2i-1] | -->+ \<- | bk | \<- | bk | | |
| +--------+ | +--------+ +--------+ | |
| | | |
| +----------------------------------------------+---+
| |
+<----------------------------------------------------------------+
XXX
显示了反向偏移量,该偏移量允许指针保持一致。