【问题标题】:bin_at in dlmallocdlmalloc 中的 bin_at
【发布时间】:2010-04-28 17:34:06
【问题描述】:

在 glibc malloc.c 或 dlmalloc 中说“重新定位技巧”就像在自爆,并在 bin_at 中使用这个技巧。

bins 是一个数组,空间是在分配 av(struct malloc_state) 时分配的。不是吗? sizeof(bin[i]) 小于 sizeof(struct malloc_chunk*)?

调用bin_at(M,1)(用作unsorted_chunks)时,结果为:bin[0] - offsetof (struct malloc_chunk, fd) bin[0] - 8 对吗?

谁能为我描述一下这个技巧?我无法理解 bin_at 宏。为什么他们使用这种方法获取 bins 地址?它是如何工作的?

非常感谢,抱歉我的英语不好。

/*
     To simplify use in double-linked lists, each bin header acts
    as a malloc_chunk. This avoids special-casing for headers.
    But to conserve space and improve locality, we allocate
    only the fd/bk pointers of bins, and then use repositioning tricks
    to treat these as the fields of a malloc_chunk*.
*/

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))

malloc_chunk 结构如下:

struct malloc_chunk {

  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

而 bin 类型是这样的:

typedef struct malloc_chunk* mbinptr;

struct malloc_state {
  /* Serialize access.  */
  mutex_t mutex;

  /* Flags (formerly in max_fast).  */
  int flags;

#if THREAD_STATS
  /* Statistics for locking.  Only used if THREAD_STATS is defined.  */
  long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif

  /* 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];

  /* Linked list */
  struct malloc_state *next;

#ifdef PER_THREAD
  /* Linked list for free arenas.  */
  struct malloc_state *next_free;
#endif

  /* Memory allocated from the system in this arena.  */
  INTERNAL_SIZE_T system_mem;
  INTERNAL_SIZE_T max_system_mem;
};

【问题讨论】:

    标签: c malloc


    【解决方案1】:

    大概struct malloc_chunk 看起来像:

    struct malloc_chunk {
        /* ... fields here ... */
        struct malloc_chunk *fd;
        struct malloc_chunk *bk;
        /* ... more fields here ... */
    };
    

    ...->bins 类型看起来像:

    struct {
        struct malloc_chunk *fd;
        struct malloc_chunk *bk;
    };
    

    bin_at 宏将指向后一个结构的指针变成指向前一个结构的假指针,仅用于访问 fdbk 成员(因为它们是唯一存在于较小的那个)。即bin_at(m, i)->fdbin_at(m, i)->bkm->bins[(i - 1) * 2].fdm->bins[(i - 1) * 2].bk 相同,但是bin_at 可以用于期望struct malloc_chunk * 的地方(只要它们只使用fdbk成员)。

    这有点小题大做。我不会在你自己的代码中这样做——记住 Kernighan 关于尽可能巧妙地编写代码的建议:

    "调试比写作难 首先是代码。 因此,如果您将代码编写为 尽可能聪明地,你是,通过 定义,不够聪明,无法调试 它。”——Brian W. Kernighan


    好的,所以 ->bins 根本不是结构数组 - 它是 struct malloc_chunk * 的数组。

    注意->bins[(i - 1) * 2] 指的是->bins 数组中struct malloc_chunk * 指针的第i 个。这对等价于struct malloc_chunk 中的fdbk 对指针,其中第一个(->bins[(i - 1) * 2]) 等价于fd(他们可以改为使->bins 成为一个较小的数组我在上面建议的结构;它在功能上是等效的并且可能更清晰)。

    bin_at 宏允许代码将->bins 数组中的一对指针插入struct malloc_chunk 结构的链表中,而无需分配整个struct malloc_chunk。这就是他们所说的节省空间。

    bin_at 宏获取bins 数组的索引,然后执行“如果此指针实际上是struct malloc_chunk 中的fd 值,则计算指向struct malloc_chunk 所在位置的指针” .它通过从bins 数组中的项目地址中减去struct malloc_chunk 中的fd 成员的偏移量来实现这一点。

    它并没有真正“找到bins[i]”——这很简单(&bins[i])。它实际上定位了bins[i]fd 成员的虚构 struct malloc_chunk

    抱歉,解释起来很复杂,因为这是一个复杂的概念。

    【讨论】:

    • 非常感谢您的回答。但我仍然不知道它如何节省空间,以及它如何定位 bin[i]。我编辑了问题并粘贴了更多代码。请您详细描述一下吗?
    • 我想我明白了。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多