dlmalloc中的bin_at

时间:2010-04-28 17:34:07

标签: c malloc

在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宏。为什么他们得到垃圾箱地址使用这种方法?它是如何工作的?

非常感谢,对不起我的英语不好。

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

1 个答案:

答案 0 :(得分:4)

大概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 *的地方(只要fd因为他们只使用bk->bins成员。

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

  

“调试是写入的两倍   代码首先。   因此,如果您将代码编写为   尽可能巧妙地,你是   定义,不够聪明,无法调试   它。“ - Brian W. Kernighan


好的,所以struct malloc_chunk *根本不是结构数组 - 它是->bins[(i - 1) * 2]的数组。

请注意,struct malloc_chunk *是指->bins数组中fd指针的第i个。该对等同于bk中的struct malloc_chunk->bins[(i - 1) * 2]指针对,第一对(fd)等同于->bins(他们可以拥有而是使bin_at成为我上面建议的较小结构的数组;它在功能上是等价的,可能更清晰。)

->bins宏允许代码将struct malloc_chunk数组中的一对指针插入到struct malloc_chunk结构的链表中 - 而不分配整个bin_at }。这是他们正在谈论的节省空间。

bins宏获取fd数组的索引,然后执行“如果此指针实际上是struct malloc_chunk中的struct malloc_chunk值,则计算指向那里fd将是“。它通过从struct malloc_chunk数组中的项目地址中减去bins成员bins[i]成员的偏移量来实现此目的。

它并没有真正“找到&bins[i]” - 这很简单(struct malloc_chunk)。它实际上找到了{em>虚构 bins[i]fd是{{1}}成员。

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