malloc fastbin

首先定义了 REMOVE_FB

#define REMOVE_FB(fb, victim, pp)			\
do							\
{							\
victim = pp;					\
if (victim == NULL)				\
break;						\
pp = REVEAL_PTR (victim->fd);                                     \
if (__glibc_unlikely (pp != NULL && misaligned_chunk (pp)))       \
malloc_printerr ("malloc(): unaligned fastbin chunk detected"); \
}							\
while ((pp = catomic_compare_and_exchange_val_acq (fb, pp, victim)) \
!= victim);					\

这个宏函数在获取fastbin成功时,且为多线程时触发。其中fb为指向fastbinY数组中某一项的指针,victim为要返回的chunk的指针,pp为一个临时的chunk指针。

if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
  {
      idx = fastbin_index (nb);
      mfastbinptr *fb = &fastbin (av, idx);
      mchunkptr pp;
      victim = *fb;

fastbin分配的核心代码,其中nb为要分配的chunk大小,根据nb计算出对应的idx,根据idx获取fastbinY数组中某一项的指针fbfb指向一个chunk,最后victim也指向该chunk。

if (victim != NULL)
{
    if (__glibc_unlikely (misaligned_chunk (victim)))
          malloc_printerr ("malloc(): unaligned fastbin chunk detected 2");

    if (SINGLE_THREAD_P)
          *fb = REVEAL_PTR (victim->fd);
    else
          REMOVE_FB (fb, pp, victim);

如果找到了相应的chunk,也就是分配成功了。检查1:chunk是否是对齐的。然后将victim从链表中清除,将victim->fd存放到fastbinY数组里。这里考虑了多线程的问题。这里我们只看单线程的代码

#define PROTECT_PTR(pos, ptr) \
  ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#define REVEAL_PTR(ptr)  PROTECT_PTR (&ptr, ptr)

这里将&(victim->fd)右移12位(页面大小)与victim->fd异或,这是一个加密手段,对fd的后48位进行加密。x^x=00^x=x所以有x^x^x=x

if (__glibc_likely (victim != NULL))
      {
          size_t victim_idx = fastbin_index (chunksize (victim));
          if (__builtin_expect (victim_idx != idx, 0))
              malloc_printerr ("malloc(): memory corruption (fast)");

如果完成链表清除后,victim != NULL的话,检查2:取出的chunk是否与预期一致。

          check_remalloced_chunk (av, victim, nb);
          void *p = chunk2mem (victim);
	      alloc_perturb (p, bytes);
	      return p;
	    }
	}

这里check_remalloced_chunk对取出的chunk做一个检查,如果没问题的话就返回victim[2]给用户空间

static void
do_check_remalloced_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T s)
{
  INTERNAL_SIZE_T sz = chunksize_nomask (p) & ~(PREV_INUSE | NON_MAIN_ARENA);

  if (!chunk_is_mmapped (p))
    {
      assert (av == arena_for_chunk (p));
      if (chunk_main_arena (p))
        assert (av == &main_arena);
      else
        assert (av != &main_arena);
    }

  do_check_inuse_chunk (av, p);

  /* Legal size ... */
  assert ((sz & MALLOC_ALIGN_MASK) == 0);
  assert ((unsigned long) (sz) >= MINSIZE);
  /* ... and alignment */
  assert (aligned_OK (chunk2mem (p)));
  /* chunk is less than MINSIZE more than request */
  assert ((long) (sz) - (long) (s) >= 0);
  assert ((long) (sz) - (long) (s + MINSIZE) < 0);
}

主要是检查chunk的标志位是否正确

posted @ 2022-11-21 16:07  benoqtr  阅读(381)  评论(0编辑  收藏  举报