Daily Heap #8

juuun0·2022년 2월 8일
1

Heap-A-to-Z

목록 보기
8/10
post-thumbnail

malloc() in glibc 2.23

_int_malloc()

Smallbin Size

Request size가 fastbin size에 해당되지 않을 경우 다음으로 smallbin size에 해당되는지 확인하는 routine을 거칩니다. 구현 코드는 다음과 같습니다.

3405   if (in_smallbin_range (nb))
3406     {
3407       idx = smallbin_index (nb);
3408       bin = bin_at (av, idx);
3409 
3410       if ((victim = last (bin)) != bin)
3411         {
3412           if (victim == 0) /* initialization check */
3413             malloc_consolidate (av);
3414           else
3415             {
3416               bck = victim->bk;
3417         if (__glibc_unlikely (bck->fd != victim))
3418                 {
3419                   errstr = "malloc(): smallbin double linked list corrupted";
3420                   goto errout;
3421                 }
3422               set_inuse_bit_at_offset (victim, nb);
3423               bin->bk = bck;
3424               bck->fd = bin;
3425 
3426               if (av != &main_arena)
3427                 victim->size |= NON_MAIN_ARENA;
3428               check_malloced_chunk (av, victim, nb);
3429               void *p = chunk2mem (victim);
3430               alloc_perturb (p, bytes);
3431               return p;
3432             }
3433         }
3434     }

Init

Request size가 전체 smallbin range에 해당되는지 확인합니다. 만약 해당되지 않을 경우 Largebin 범위로 넘어가며, 해당될 경우 몇 가지 초기화 작업을 진행합니다.

smallbin_index() 매크로를 호출하여 request size가 해당되는 smallbin의 index를 구합니다. Smallbin의 자세한 구조는 별도의 게시글에서 정리 후 추가할 예정입니다.

다음으로 현재 arena에서 idx에 해당되는 bin을 가져옵니다.


Empty Check

last() 매크로의 경우 해당 bin에서 가장 마지막 chunk를 가져옵니다. 따라서 victim에 저장된 값이 현재 bin의 주소와 같지 않을 경우 사용 가능한 freed chunk가 존재함을 의미합니다. Freed chunk가 존재하지 않을 경우 아래의 과정을 진행하지 않고 구문으로 이동합니다.

만약 victim이 '0' 일 경우는 initialization 과정에 해당되며 malloc_consolidate() 함수를 호출합니다.


Smallbin Check

bckvictim -> bk 값을 저장한 뒤 bck -> fd 값이 'victim' 과 일치하는지 확인합니다. 이 과정은 Doubly Linked List가 변조되지 않았는지 확인하는 과정으로, 정상적인 smallbin의 경우 현재 chunk의 이전 chunk는 당연히 'fd' 값으로 현재 chunk를 가리켜야 함을 의미합니다.


Allocate Freed Chunk

적합한 Free chunk가 존재할 경우 이를 Allocated Chunk로 변환하기 위한 과정이 수행됩니다.

먼저 set_inuse_bit_at_offset() 매크로를 호출하여 할당할 chunk와 인접한 다음 chunkprev_inuse flag를 set 상태로 변경합니다. 이는 smallbin의 경우 free 과정에서 prev_inuse flag를 unset 하기 때문에 수행됩니다.

다음으로 bin -> bkbck로 변경하고 bck -> fdbin으로 변경합니다. 이는 double linked list에서 할당 대상인 'victim' 을 제거하는 역할을 합니다.

마지막으로 해당 chunk가 main_arena에 속하는지 여부를 검사한 뒤에 최종적으로 'victim' 의 mem 주소를 반환합니다.


Reference

profile
To be

0개의 댓글