了解glibc malloc分箱实现

问题描述

最近我一直在研究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显示了反向偏移量,该偏移量允许指针保持一致。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...