/* Try to use top chunk */ /* Require that there be a remainder, ensuring top always exists */ if ( (remainder_size = chunksize(top(ar_ptr)) - nb) < (long)MINSIZE) {
#if HAVE_MMAP /* If the request is big and there are not yet too many regions, and we would otherwise need to extend, try to use mmap instead. */ if ((unsignedlong)nb >= (unsignedlong)mmap_threshold && n_mmaps < n_mmaps_max && (victim = mmap_chunk(nb)) != 0) return victim; /* 如果申请字节超过“topchunk->size”,调用mmap_chunk */ #endif
/* Try to extend */ malloc_extend_top(ar_ptr, nb); if ((remainder_size = chunksize(top(ar_ptr)) - nb) < (long)MINSIZE) { #if HAVE_MMAP /* A last attempt: when we are out of address space in a non-main arena, try mmap anyway, as long as it is allowed at all. */ if (ar_ptr != &main_arena && n_mmaps_max > 0 && (victim = mmap_chunk(nb)) != 0) return victim; /* 如果,第一次调用mmap_chunk没有成功,则再调用一次 */ #endif return0; /* propagate failure */ } } victim = top(ar_ptr); set_head(victim, nb | PREV_INUSE); /* 设置top chunk的头 */ top(ar_ptr) = chunk_at_offset(victim, nb); set_head(top(ar_ptr), remainder_size | PREV_INUSE); /* 设置剩下chunk的头 */ check_malloced_chunk(ar_ptr, victim, nb); /* 这个检查几乎没有影响 */ return victim;
if (av != &main_arena) { heap_info *old_heap, *heap; size_t old_heap_size;
/* First try to extend the current heap. */ old_heap = heap_for_ptr (old_top); old_heap_size = old_heap->size; if ((long) (MINSIZE + nb - old_size) > 0 /* top chunk不够用,grow_heap扩展top chunk的空间 */ /* 要打House Of Force,这个if一定不成立(old_size非常大) */ && grow_heap (old_heap, MINSIZE + nb - old_size) == 0) { av->system_mem += old_heap->size - old_heap_size; set_head (old_top, (((char *) old_heap + old_heap->size) - (char *) old_top) | PREV_INUSE); } elseif ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad))) { /* Use a newly allocated heap. */ heap->ar_ptr = av; heap->prev = old_heap; av->system_mem += heap->size; /* Set up the new top. */ top (av) = chunk_at_offset (heap, sizeof (*heap)); set_head (top (av), (heap->size - sizeof (*heap)) | PREV_INUSE);
/* Setup fencepost and free the old top chunk with a multiple of MALLOC_ALIGNMENT in size. */ /* The fencepost takes at least MINSIZE bytes, because it might become the top chunk again later. Note that a footer is set up, too, although the chunk is marked in use. */ old_size = (old_size - MINSIZE) & ~MALLOC_ALIGN_MASK; set_head (chunk_at_offset (old_top, old_size + 2 * SIZE_SZ), 0 | PREV_INUSE); if (old_size >= MINSIZE) /* 需要分割 */ { set_head (chunk_at_offset (old_top, old_size), (2 * SIZE_SZ) | PREV_INUSE); set_foot (chunk_at_offset (old_top, old_size), (2 * SIZE_SZ)); set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA); _int_free (av, old_top, 1); } else/* 不需要分割 */ { set_head (old_top, (old_size + 2 * SIZE_SZ) | PREV_INUSE); set_foot (old_top, (old_size + 2 * SIZE_SZ)); } } elseif (!tried_mmap) /* We can at least try to use to mmap memory. */ goto try_mmap; } ................
这里只展示了“av != &main_arena”,不是 House Of Force 的重点,而“av == &main_arena”太长不方便展示,给出部分代码方便查源码时定位
程序复杂了不少,也多了许多检查:
1 2
/* top chunk is OK */ check_chunk (av, av->top);
1
# define check_chunk(A, P) do_check_chunk (A, P)
1 2 3
/* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem;