前言

本文贴一些ptmalloc(glibc2.31版本)简单的参数,以及用到的便利函数

有必要说明一下,作者对这些取值的解释基本都是in practice(也有少数是必要的设计),因此也不用过于纠结,见识一下吧

背景

这里就不介绍ptmalloc的完整设计了,一方面是自己也没时间全部分析,另一方面是网上挺多优质介绍的

我目前对ptmalloc里的数据结构做了一些简单RTFSC分析,和下面的内容强关联,感兴趣也可看看:

malloc at master · Caturra000/RTFSC · GitHub

最小大小

/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE  \
  (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))

/* The smallest possible chunk */
#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))

/* The corresponding bit mask value.  */
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)

/* MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.  It
   must be a power of two at least 2 * SIZE_SZ, even on machines for
   which smaller alignments would suffice. It may be defined as larger
   than this though. Note however that code and data structures are
   optimized for the case of 8-byte alignment.  */
#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \
              ? __alignof__ (long double) : 2 * SIZE_SZ)
// 注:long double为16字节

/* The corresponding word size.  */
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
// 等同于size_t

这里使用+~操作进行对齐补位

MASK需要二进制全1111

这样算出来是MASK+1的倍数(包括0)

MINSIZE等价于MIN_CHUNK_SIZE


由offset可得,具体完整大小在64位下是32字节

chunk header + fd + bk

这应该是指带元数据下的大小,如果是用户请求,那就是最小16字节

因此你尝试malloc(0)可能是直接padding到16字节的 (但是也允许返回errno

follow up:最大大小呢?

见上面RTFSC链接

对齐判断

/* Check if m has acceptable alignment */
#define aligned_OK(m)  (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)

mmap阈值

/* There is only one instance of the malloc parameters.  */
static struct malloc_par mp_ =
{
  .top_pad = DEFAULT_TOP_PAD,
  .n_mmaps_max = DEFAULT_MMAP_MAX,
  .mmap_threshold = DEFAULT_MMAP_THRESHOLD,
  .trim_threshold = DEFAULT_TRIM_THRESHOLD,
#define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
  .arena_test = NARENAS_FROM_NCORES (1)
#if USE_TCACHE
  ,
  .tcache_count = TCACHE_FILL_COUNT,
  .tcache_bins = TCACHE_MAX_BINS,
  .tcache_max_bytes = tidx2usize (TCACHE_MAX_BINS-1),
  .tcache_unsorted_limit = 0 /* No limit.  */
#endif
};

#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN
#endif

/*
  MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically
  adjusted MMAP_THRESHOLD.
*/
#ifndef DEFAULT_MMAP_THRESHOLD_MIN
#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)
#endif

mmap阈值并不区分32位还是64位,总是128KB

bin划分

#define NBINS             128

fast bins外,总个数为128

#define NFASTBINS  (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)

/* The maximum fastbin request size we support */
#define MAX_FAST_SIZE     (80 * SIZE_SZ / 4)

/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
   if passed a literal constant.  */
#define request2size(req)                                         \
  (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?             \
   MINSIZE :                                                      \
   ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
  ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)

手算是不可能的,放到vs code里看看

算出fast bins个数NFASTBINS为10

并且可以知道,fast bins的最大阈值为160字节

#define NSMALLBINS         64

small bins的个数是64?其实是62,看RTFSC怎么算的

#define MIN_LARGE_SIZE    ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)

这是用于划分small bins和large bins的值,64位下位1024

既大于等于1024的chunk才有资格放入large bin

TODO 公差数组

References

malloc - Glibc source code (glibc-2.31) - Bootlin