__libc_malloc는 tcache에서 청크를 가져오려고 시도하며, 실패할 경우 _int_malloc을 호출합니다.
_int_malloc :
아레나가 없으면 생성하려고 시도합니다.
올바른 크기의 빠른 빈 청크가 있으면 사용합니다.
다른 빠른 청크로 tcache를 채웁니다.
올바른 크기의 작은 빈 청크가 있으면 사용합니다.
해당 크기의 다른 청크로 tcache를 채웁니다.
요청된 크기가 작은 빈에 해당하지 않으면, 빠른 빈을 정렬되지 않은 빈으로 통합합니다.
정렬되지 않은 빈을 확인하고, 충분한 공간이 있는 첫 번째 청크를 사용합니다.
발견된 청크가 더 크면, 일부를 반환하기 위해 나누고 나머지를 정렬되지 않은 빈에 다시 추가합니다.
청크가 요청된 크기와 동일하면, 반환하는 대신 tcache를 채우기 위해 사용합니다( tcache가 가득 찰 때까지, 그 후 다음 것을 반환).
확인된 각 작은 크기의 청크는 해당하는 작은 빈 또는 큰 빈에 넣습니다.
요청된 크기의 인덱스에서 큰 빈을 확인합니다.
요청된 크기보다 큰 첫 번째 청크에서부터 확인을 시작하고, 발견되면 반환하고 나머지를 작은 빈에 추가합니다.
끝까지 다음 인덱스의 큰 빈을 확인합니다.
다음 더 큰 인덱스에서 청크를 확인하고, 발견된 첫 번째 청크를 나누어 요청된 크기에 사용하고 나머지를 정렬되지 않은 빈에 추가합니다.
이전 빈에서 아무것도 발견되지 않으면, 상단 청크에서 청크를 가져옵니다.
상단 청크가 충분히 크지 않으면 sysmalloc로 확장합니다.
__libc_malloc
malloc 함수는 실제로 __libc_malloc을 호출합니다. 이 함수는 원하는 크기의 사용 가능한 청크가 있는지 tcache를 확인합니다. 만약 있다면 그것을 사용하고, 없다면 단일 스레드인지 확인한 후, 그 경우에는 메인 아레나에서 _int_malloc을 호출하며, 그렇지 않으면 스레드의 아레나에서 _int_malloc을 호출합니다.
__libc_malloc code
```c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
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);
</details>
반환된 포인터가 항상 `tag_new_usable`로 태그된다는 점에 유의하세요, 코드에서:
```c
void *tag_new_usable (void *ptr)
Allocate a new random color and use it to color the user region of
a chunk; this may include data from the subsequent chunk's header
if tagging is sufficiently fine grained. Returns PTR suitably
recolored for accessing the memory there.
_int_malloc
이것은 다른 빈과 상단 청크를 사용하여 메모리를 할당하는 함수입니다.
시작
요청된 메모리 공간이 가져야 할 실제 크기를 정의하고 몇 가지 변수를 설정하는 것으로 시작합니다:
Fast Bin
필요한 크기가 Fast Bins 크기 내에 있다면, fast bin에서 청크를 사용해 보십시오. 기본적으로 크기를 기반으로 유효한 청크가 위치해야 할 fast bin 인덱스를 찾고, 있다면 그 중 하나를 반환합니다.
게다가, tcache가 활성화되어 있다면, 해당 크기의 tcache bin을 fast bins로 채웁니다.
이러한 작업을 수행하는 동안 몇 가지 보안 검사가 실행됩니다:
청크가 정렬되지 않은 경우: malloc(): unaligned fastbin chunk detected 2
포워드 청크가 정렬되지 않은 경우: malloc(): unaligned fastbin chunk detected
반환된 청크의 크기가 fast bin의 인덱스 때문에 올바르지 않은 경우: malloc(): memory corruption (fast)
tcache를 채우는 데 사용된 청크가 정렬되지 않은 경우: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
작은 청크가 아니라면, 큰 청크이며 이 경우 **malloc_consolidate**가 메모리 단편화를 피하기 위해 호출됩니다.
정렬되지 않은 빈
유효한 청크를 사용하기 위해 정렬되지 않은 빈을 확인할 시간입니다.
시작
이는 while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av)) 를 사용하여 정렬되지 않은 빈을 bk 방향으로 탐색하는 큰 for 루프에서 시작됩니다.
또한, 새로운 청크가 고려될 때마다 몇 가지 보안 검사가 수행됩니다:
청크 크기가 이상한 경우 (너무 작거나 너무 큼): malloc(): invalid size (unsorted)
다음 청크 크기가 이상한 경우 (너무 작거나 너무 큼): malloc(): invalid next size (unsorted)
다음 청크가 나타내는 이전 크기가 청크의 크기와 다를 경우: malloc(): mismatching next->prev_size (unsorted)
victim->bck->fd == victim이 아니거나 victim->fd == av (arena)가 아닐 경우: malloc(): unsorted double linked list corrupted
우리는 항상 마지막 것을 확인하고 있으므로, fd는 항상 arena 구조체를 가리켜야 합니다.
다음 청크가 이전 청크가 사용 중임을 나타내지 않는 경우: malloc(): invalid next->prev_inuse (unsorted)
이것이 성공적이었다면, 청크를 반환하고 끝내고, 그렇지 않으면 함수를 계속 실행합니다...
크기가 같을 경우
요청된 크기가 청크의 크기와 정확히 일치하는 경우, 빈에서 청크를 계속 제거합니다:
tcache가 채워지지 않았다면, tcache에 추가하고 사용할 수 있는 tcache 청크가 있음을 계속 표시합니다.
tcache가 가득 차 있다면, 그냥 사용하여 반환합니다.
_int_malloc 한계
이 시점에서 사용 가능한 tcache에 일부 청크가 저장되어 있고 한계에 도달하면, 그냥 tcache 청크를 반환합니다.
게다가, MAX_ITERS에 도달하면 루프에서 벗어나 다른 방법으로 청크를 가져옵니다 (top chunk).
return_cached가 설정되어 있으면, 더 큰 검색을 피하기 위해 tcache에서 청크를 반환합니다.
이 경우에 적합한 청크가 발견되지 않으면 계속 진행합니다.
대형 빈 (다음 더 큰 것)
정확한 대형 빈에 사용할 수 있는 청크가 없으면, 다음 대형 빈(즉시 더 큰 것부터 시작) 전체를 반복하여 하나가 발견될 때까지(있는 경우) 확인합니다.
분할된 청크의 나머지는 정렬되지 않은 빈에 추가되며, last_reminder가 업데이트되고 동일한 보안 검사가 수행됩니다:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc 시작
arena가 null이거나 요청된 크기가 너무 크면(허용된 mmaps가 남아있고) sysmalloc_mmap을 사용하여 공간을 할당하고 반환합니다.
sysmalloc not main arena
먼저 이 힙을 위해 이전 힙을 확장하려고 시도합니다. 불가능할 경우 새 힙을 할당하고 이를 사용할 수 있도록 포인터를 업데이트하려고 합니다.
마지막으로 그것이 작동하지 않으면 **sysmalloc_mmap**을 호출하려고 시도합니다.
sysmalloc main arena previous error 1
이전이 MORECORE_FAILURE를 반환한 경우, sysmalloc_mmap_fallback을 사용하여 메모리를 다시 할당해 보십시오.
sysmalloc finale
할당을 완료하고 아레나 정보를 업데이트합니다.
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2921C3-L2943C12if ((unsignedlong) av->system_mem > (unsignedlong) (av->max_system_mem))av->max_system_mem = av->system_mem;check_malloc_state (av);/* finally, do the allocation */p = av->top;size =chunksize (p);/* check that one of the above allocation paths succeeded */if ((unsignedlong) (size) >= (unsignedlong) (nb + MINSIZE)){remainder_size = size - nb;remainder =chunk_at_offset (p, nb);av->top = remainder;set_head (p, nb | PREV_INUSE | (av !=&main_arena ? NON_MAIN_ARENA :0));set_head (remainder, remainder_size | PREV_INUSE);check_malloced_chunk (av, p, nb);returnchunk2mem (p);}/* catch all failure paths */__set_errno (ENOMEM);return0;