主要探究一下malloc和free是如何执行的
!!!说明:本文是杂文,可能只有我能看懂,仅供复习参考使用,不定期更新

malloc

真正发挥作用的是_int_malloc

但是call malloc是__libc_malloc

在__libc_malloc中会调用_int_malloc

整个heap的信息都记录在struct malloc_state中,称为main_arena

__libc_malloc主体部分如下
hook取得__malloc_hook部分内容
如果指针hook != 0 就调用hook函数
(第一次调用malloc时,__malloc_hook里面其实是有一个叫malloc_hook_ini的函数,该函数首先把__mallochook置0防止再次调用(因为返回地址是__libc_malloc,然后调用了ptmalloc_init()这个做初始化工作的主体函数)

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_get (ar_ptr, bytes);

  victim = _int_malloc (ar_ptr, bytes);
  /* 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);
    }
  if (ar_ptr != NULL)
    __libc_lock_unlock (ar_ptr->mutex);
  assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
          ar_ptr == arena_for_chunk (mem2chunk (victim)));
  return victim;
}

点进去arena_get

/* arena_get() acquires an arena and locks the corresponding mutex.
   First, try the one last locked successfully by this thread.  (This
   is the common case and handled with a macro for speed.)  Then, loop
   once over the circularly linked list of arenas.  If no arena is
   readily available, create a new one.  In this latter case, `size'
   is just a hint as to how much memory will be required immediately
   in the new arena. */
#define arena_get(ptr, size) do { \
      ptr = thread_arena;                                                      \
      arena_lock (ptr, size);                                                      \
  } while (0)

我们直接上手跟踪好了

#Include <stdio.h>
#include <stdlib.h>
int main()
{
    void *p,*q;
    p = malloc(100);
    q = malloc(16);
    return 0;
}

可以看到,第一次调用malloc时,会进去malloc_hook_ini函数

执行完后返回到__libc_malloc函数里面

free

我们通过这个demo看一下free过程中发生了啥

#include <stdio.h>
#include <stdio.h>
#include <string.h>

int main()
{
        void *p,*q,*r;
        p = malloc(150);
        q = malloc(150);
        r = malloc(150);

        free(p);
        free(r);
        free(q);
}

如图,我们现在申请了三个chunk

free掉一块,可以看到进入unsorted bin中去

把r free掉,可以看到直接和top chunk合并了

思考:如果free q后,是q先和p合并呢还是先和topchunk合并呢??
调试小技巧

可以看到,其实是先和前一块chunk进行合并的
size加上prevsize之类的

小技巧,p *(struct malloc_state*)address可以将某个地址的堆块详细信息打印出来
可以看到,最终三个chunk都被top chunk合并起来