malloc
最简单的一个申请堆空间:
void *malloc(size_t bytes) //分配所需的内存空间,并返回一个指向它的指针
//参数必须是2*SIZE_SZ的整数倍,如果不是系统会优化为整数倍
//32bit中SIZE_SE为4,也就是堆大小为8的倍数。
//64bit中SIZE_SZ为8,那么就是16的倍数。
- 第一次调用malloc的时候会先初始化一个叫main_arena(libc中)的东西,并向kernel申请一大块内存区域(top tunck)作为堆
- 再从这一大块内存区域分割出一个chunk,让malloc回传给程序(这个回传值是一个指针,这个指针指向这个chunk头,tcache前是指向presize,tcache后是指向tcache的数据体)。此时使用的这块内存叫chunk
源码角度:
- 首先会进入到__libc_malloc(size_t bytes)函数
- 然后会寻找合适的arena来分配内存
- 如果没找到就来到 _int_malloc()函数分配内存
_int_malloc
- 首先将用户请求的bytes(参数一)转换为chunk单位nb
- 如果没有合适的arena则调用sysmalloc(),用mmap()分配chunk并返回,也就是区分是main线程还是子线程
mmap()
:为了更快的找到最合适的堆块搜索顺序为如下
sysmalloc()
:当申请的大小(nb):
- 大于
mp_.mmap_threshold(128 * 1024 byte)
时,通过mmap()函数分配 - 小于时用brk()扩展内存形成新的top chunk,从而旧的 top chunk将被释放掉。从新的top chunk中切分nb大小的chunk给用户
free 释放堆空间
void free(void *mem)//指针指向一个要释放内存的chunk地址
//该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的
//如果传递的参数是一个空指针,则不会执行任何动作。
调用free函数释放指定堆空间时:
- 先进入到__libc_free()函数,将指向user data的指针转换为指向chunk的指针
- 如果是mmap()函数返回的chunk则通过munmap_chunk()函数释放
- 反之获取指向arena的指针,调用 _int_free()函数进行释放
_int_free
调用流程:
- 首先获得要释放chunk的大小
- 对其进行检查size是否过小或对齐
- 判断该chunk是否再fast bin范围内
- 如果是则插入fast bin -> 判断chunk是否由mmap()函数生成
- 如果不是则进行合并(先向后合并再前合并)
- 合并之后的chunk超过了
FASTBIN_CONSOLIDATION_THRESHOLD
则整理fast bin并返回给系统
释放内存流程如下:
fast chunk就直接进入fast bin先进后出,其他bin则先进入unsort bin充当缓存作用
当在之后申请内存时流程如下:(满足一个条件即退出流程)
划分)
%%--------------------------------------------------------------------