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
数组中某一项的指针fb
,fb
指向一个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=0
而0^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的标志位是否正确