Daily Heap #4

juuun0·2022년 1월 26일
1

Heap-A-to-Z

목록 보기
4/10
post-thumbnail

malloc_chunk

Heap 영역에서는 chunk라는 단위로 메모리를 관리합니다. Chunk에 관한 정의는 malloc.c 파일의 malloc_chunk 구조체로 정의되어 있으며 내용은 아래와 같습니다.

struct malloc_chunk {
  INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk, if it is free. */
  INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;                /* double links -- used only if this chunk is free. */
  struct malloc_chunk* bk;
  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
  struct malloc_chunk* bk_nextsize;
};

typedef struct malloc_chunk* mchunkptr;

정의된 내용을 가반으로 chunk의 상태에 따라 allocated chunk와 freed chunk로 구분할 수 있습니다. 두 chunk의 차이점을 설명하기 이전에 먼저 공통점을 설명하겠습니다.


prev_size & size

malloc_chunk 구조체에는 두 개의 INTERNAL_SIZE_T 타입의 변수가 존재합니다.

prev_size의 경우 인접한 이전 chunk의 size 값을 저장하고 있습니다. 이는 인접한 이전 chunk가 freed chunk일 때 값이 저장됩니다.

size의 경우 현재 chunk의 size 값을 저장하고 있습니다. 여기서 size는 요청한 크기가 아닌 overhead를 포함한 실제 할당된 크기를 의미합니다. size의 경우 하위 3 bit는 flag 목적으로 예약되어 있습니다.


Flag

Chunk의 상태를 관리하기 위한 flag로 순서대로 A, M, P flag가 존재합니다. 각 flag를 가중치 코드로 변환할 경우 A = 4, M = 2, P = 1의 값을 가집니다.

A(NON_MAIN_ARENA)

A flag는 해당 chunk가 main arena가 아닌 다른 arena에 의해 관리될 경우 이를 "set" 으로 설정합니다. 따라서 Sub thread에 의해 생성된 chunk는 이 값을 항상 "set" 으로 가지게 됩니다.

M(IS_MMAPPED)

mmap() 함수를 통해 할당된 경우 해당 bit를 "set" 으로 설정합니다.

P(PREV_INUSE)

P flag는 물리적으로 인접한 이전 chunk가 사용 중(allocated)일 경우 해당 bit를 "set" 으로 설정합니다. 만약 인접한 이전 chunk가 free 될 경우 현재 chunk의 P flag를 0으로 지정하며 이전 chunk의 size를 현재 chunk의 prev_size에 저장합니다.

이론적으로는 chunk의 size에 대한 언급이 존재하지 않지만, 실제 분석을 하게 될 경우 tcache, fastbin에서는 P flag의 변경이 이루어지지 않는 것을 확인할 수 있었습니다. 이에 대한 내용은 free() 함수 분석 시 기술할 예정입니다.


Allocated Chunk

Allocated Chunk의 경우 malloc_chunk의 구조체에서 fd, bk, fd_nextsize, bk_nextsize 항목을 사용하지 않습니다. 아래 내용은 allocated chunk의 구조를 형상화한 것 입니다.

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if unallocated (P clear)  |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk, in bytes                     |A|M|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             User data starts here...                          .
            .                                                               .
            .             (malloc_usable_size() bytes)                      .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             (size of chunk, but used for application data)    |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of next chunk, in bytes                |A|0|1|
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

실제로 할당을 진행하게 되면 return 값이 가리키는 주소는 mem 위치가 됩니다. 또한 기존의 fd, bk, fd_nextsize, bk_nextsize 공간은 User Data를 저장하며 다음 chunk의 prev_size 또한 User Data를 저장하는데 활용될 수 있습니다.


Freed Chunk

Freed Chunk의 경우 chunk의 size에 따라 다른 동작을 수행하게 됩니다.

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if unallocated (P clear)  |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                     |A|0|P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Forward pointer to next chunk in list             |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Back pointer to previous chunk in list            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Unused space (may be 0 bytes long)                .
            .                                                               .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `foot:' |             Size of chunk, in bytes                           |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of next chunk, in bytes                |A|0|0|
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Size에 따라 적절한 처리 과정을 거쳐 bin list에 저장되며 bin list를 유지하기 위해 필요한 값들이 setting 됩니다. 자세한 내용에 대해서는 각 bin list 분석 중 설명할 예정입니다.


Reference

profile
To be

0개의 댓글