建议学习 Glibc内存管理 Ptmalloc2源代码分析(ps自行百度)
参考 蓝帽杯赛前直播 主播ppt 和 CTF-wiki
一. malloc
我们使用malloc时,函数真正调用的是__libc_malloc
函数,该函数只是用来简单封装_int_malloc
函数。注意:用户申请的字节一旦进入申请内存函数中就变成了无符号整数。
__libc_malloc
// wapper for int_malloc
void *__libc_malloc(size_t bytes) {
mstate ar_ptr;
void * victim;
首先检查是否有内存分配钩子,如果有,调用钩子并返回。
void *(*hook)(size_t, const void *) = atomic_forced_read(__malloc_hook);
if (__builtin_expect(hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS(0));
寻找一个arena来试图分配内存。
arena_get(ar_ptr, bytes);
调用_int_malloc函数去申请对应的内存。
victim = _int_malloc(ar_ptr, bytes);
如果分配内存失败,ptmalloc会尝试再去寻找一个可用的arena,并分配内存。
/* Retry with another arena only if we were able to find a usable arena
before. */
if (!victim && ar_ptr != NULL) {
LIBC_PROBE(memory_malloc_retry, 1, bytes);
ar_ptr = arena_get_retry(ar_ptr, bytes);
victim = _int_malloc(ar_ptr, bytes);
}
如果申请到了arena,在退出前需要解锁。
if (ar_ptr != NULL) __libc_lock_unlock(ar_ptr->mutex);
判断目前的状态是否满足以下条件
1.没有申请到内存 2.是mmap的内存 3.申请到的内存必须在其所分配的arena中
assert(!victim || chunk_is_mmapped(mem2chunk(victim)) ||
ar_ptr == arena_for_chunk(mem2chunk(victim)));
返回内存。
return victim;
}
.............................................................................
此后省去源码分析...太繁琐,可以去wiki中查看
.............................................................................
_int_malloc
根据size
- fastbin range:从
fast bin
中查找是否有合适的chunk - small bin range:先从
small bin
查找(small bin
按照size排好,查找更快),再从unsorted bin
查找 - large bin range
- 合并所有
fastbin
查找unsorted bin
- 从
large bin
中查找满足条件且最小的chunk,有则切分,剩余的放入unsorted bin
//这是ptmalloc机制,他在分配large chunk时会先对堆中的碎片chunk进行合并,以便减少堆中的碎片
- 合并所有
- 最后从top chunk切割
- 当topchunk也无法满足时,堆分配器进行mmap内存块申请
unsorted bin分配规则(大循环 - 遍历unsorted bin)
- 尾部开始遍历
- 如果chunk size够大,切分chunk,剩下的还在unsorted bin中
- 如果不够大,将当前的chunk清出
unsorted bin
,并放入对应的bin中
- 如果分配失败
- 查找
large bin
- 扫描
small bin
/large bin
查找
- 查找
二. free
检测
- 1.size是否属于
fast bin
- 是,插入
fast bin
- 是,插入
- 2.是否是mmap分配
- 是,释放mmap的chunk
- 3.查看前一个chunk是否free
- 是,合并
- 4.查看下一个chunk是否为topchunk
- 是,合并
- 5.查看下一个chunk是否free
- 是,合并
- 6.放入
unsorted bin
网友评论