Heap analysis/glibc 2.23

(glibc 2.23) free

lok2h4rd 2022. 3. 23. 15:11

힙의 할당한 메모리를 해제할 때 사용되는 함수이다

전체 코드 아래 더보기

더보기
void
__libc_free (void *mem)
{
  mstate ar_ptr;
  mchunkptr p;                          /* chunk corresponding to mem */

  void (*hook) (void *, const void *)
    = atomic_forced_read (__free_hook);
  if (__builtin_expect (hook != NULL, 0))
    {
      (*hook)(mem, RETURN_ADDRESS (0));
      return;
    }

  if (mem == 0)                              /* free(0) has no effect */
    return;

  p = mem2chunk (mem);

  if (chunk_is_mmapped (p))                       /* release mmapped memory. */
    {
      /* see if the dynamic brk/mmap threshold needs adjusting */
      if (!mp_.no_dyn_threshold
          && p->size > mp_.mmap_threshold
          && p->size <= DEFAULT_MMAP_THRESHOLD_MAX)
        {
          mp_.mmap_threshold = chunksize (p);
          mp_.trim_threshold = 2 * mp_.mmap_threshold;
          LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
                      mp_.mmap_threshold, mp_.trim_threshold);
        }
      munmap_chunk (p);
      return;
    }

  ar_ptr = arena_for_chunk (p);
  _int_free (ar_ptr, p, 0);
}
libc_hidden_def (__libc_free)

 

 

  mstate ar_ptr;
  mchunkptr p;                          /* chunk corresponding to mem */

  void (*hook) (void *, const void *)
    = atomic_forced_read (__free_hook);
  if (__builtin_expect (hook != NULL, 0))
    {
      (*hook)(mem, RETURN_ADDRESS (0));
      return;
    }

  if (mem == 0)                              /* free(0) has no effect */
    return;

변수 선언을 하고 malloc과 동일하게 __free_hook이 존재하는지 확인하고 있다면 호출한 뒤 리턴한다

free(0)인 경우 함수가 그대로 종료된다

 

  p = mem2chunk (mem);	//free할 주소의 헤더를 포함한 주소를 구함

  if (chunk_is_mmapped (p)) // mmap으로 할당되었는지 확인
    {
      /* see if the dynamic brk/mmap threshold needs adjusting */
      if (!mp_.no_dyn_threshold
          && p->size > mp_.mmap_threshold
          && p->size <= DEFAULT_MMAP_THRESHOLD_MAX)
        {
          mp_.mmap_threshold = chunksize (p);
          mp_.trim_threshold = 2 * mp_.mmap_threshold;
          LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
                      mp_.mmap_threshold, mp_.trim_threshold);
        }
      munmap_chunk (p);
      return;
    }

  ar_ptr = arena_for_chunk (p);
  _int_free (ar_ptr, p, 0);

mem2chunk를 통해 헤더를 포함한 주소를 구하고 mmap으로 할당되었는지 확인하다

 

  ar_ptr = arena_for_chunk (p);
  _int_free (ar_ptr, p, 0);

mmap으로 할당되지 않았으면 위의 코드가 시행되는데 p의 아레나를 구한 뒤 _int_free를 호출한다

_int_free에서는 실질적인 free의 역할을 수행하는 함수로 주요 동작은 아래와 같다

  • p가 fastbin크기일 경우 fastbinY에 연결
  • p가 fastbin크기가 아닐 경우 인접한 free된 청크와 병합
  • 병합된 청크는 unsorted bin에 연결 및 병합될 청크 unlink수행
  • 청크가 largebin 크기면 fd_nextsize, bk_nextszie NULL로 초기화
  • size가 fastbin의 임계값보다 크고 fastbin에 청크가 있을때 fastbin을 병합 시킴

 

 

주요 함수 및 매크로


_int_free 링크글 - (glibc 2.23)