这篇文章我们来讲讲释放内存的过程,也就是free()的代码流程。对于应用程序来说释放内存很简单,直接调用free(ptr)就可以了,参数是要释放的内存块指针。那么,释放内存时dlmalloc做了哪些工作呢?
// 这是释放内存的函数,调用free()后执行到这里.
// 参数mem: 这是将要释放内存的指针
void dlfree(void* mem) {
/*
Consolidate freed chunks with preceeding or succeeding bordering
free chunks, if they exist, and then place in a bin. Intermixed
with special cases for top, dv, mmapped chunks, and usage errors.
*/
// 如果是空指针,那么就不需要处理了.
if (mem != 0) {
mchunkptr p = mem2chunk(mem); // 首先找到内存块的起始地址 p = mem - 8.
#if FOOTERS // 将这个宏看作是0就可以了
mstate fm = get_mstate_for(p);
if (!ok_magic(fm)) {
USAGE_ERROR_ACTION(fm, p);
return;
}
#else /* FOOTERS */
#define fm gm // 全局变量_gm_的地址
#endif /* FOOTERS */
if (!PREACTION(fm)) { // 先加锁
check_inuse_chunk(fm, p); // 检查这个chunk是否在使用中,这是一个检查函数.
if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
size_t psize = chunksize(p); // 计算这个内存块的大小.
mchunkptr next = chunk_plus_offset(p, psize); // 从这里开始是下一个内存块了.
if (!pinuse(p)) { // 如果前面一个内存块是空闲的,那么这个内存块释放后就可以跟前面一个内存块合并了.
size_t prevsize = p->prev_foot; // 前面一个内存块的大小
if ((prevsize & IS_MMAPPED_BIT) != 0) { // 如果是通过mmap方式创建的内存块
prevsize &= ~IS_MMAPPED_BIT;
psize += prevsize + MMAP_FOOT_PAD;
if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
fm->footprint -= psize;
goto postaction;
}
else { // 不是通过mmap方式创建的.
mchunkptr prev = chunk_minus_offset(p, prevsize); // 取出前面一个chunk的结构.
psize += prevsize;