(Nie wyjaśniono żadnych kontroli w tym podsumowaniu, a niektóre przypadki zostały pominięte dla zwięzłości)
__libc_malloc próbuje uzyskać kawałek z tcache, jeśli nie, wywołuje _int_malloc
_int_malloc :
Próbuje wygenerować arenę, jeśli żadna nie istnieje
Jeśli istnieje kawałek z szybkiego bin o odpowiednim rozmiarze, używa go
Wypełnia tcache innymi szybkimi kawałkami
Jeśli istnieje kawałek z małego bin o odpowiednim rozmiarze, używa go
Wypełnia tcache innymi kawałkami tego rozmiaru
Jeśli żądany rozmiar nie jest dla małych bin, konsoliduje szybki bin do niesortowanego bin
Sprawdza niesortowany bin, używa pierwszego kawałka z wystarczającą ilością miejsca
Jeśli znaleziony kawałek jest większy, dzieli go, aby zwrócić część i dodać resztę z powrotem do niesortowanego bin
Jeśli kawałek ma ten sam rozmiar co żądany rozmiar, używa go do wypełnienia tcache zamiast go zwracać (aż tcache będzie pełne, potem zwraca następny)
Dla każdego kawałka mniejszego rozmiaru sprawdzonego, umieszcza go w odpowiednim małym lub dużym bin
Sprawdza duży bin w indeksie żądanego rozmiaru
Zaczyna szukać od pierwszego kawałka, który jest większy niż żądany rozmiar, jeśli jakiś zostanie znaleziony, zwraca go i dodaje resztę do małego bin
Sprawdza duże biny z następnych indeksów aż do końca
Z następnego większego indeksu sprawdza, czy jest jakiś kawałek, dzieli pierwszy znaleziony kawałek, aby użyć go dla żądanego rozmiaru i dodaje resztę do niesortowanego bin
Jeśli nic nie zostanie znalezione w poprzednich binach, uzyskuje kawałek z górnego kawałka
Jeśli górny kawałek nie był wystarczająco duży, powiększa go za pomocą sysmalloc
__libc_malloc
Funkcja malloc faktycznie wywołuje __libc_malloc. Ta funkcja sprawdzi tcache, aby zobaczyć, czy istnieje dostępny kawałek o żądanym rozmiarze. Jeśli tak, użyje go, a jeśli nie, sprawdzi, czy jest to wątek jednowątkowy, a w takim przypadku wywoła _int_malloc w głównej arenie, a jeśli nie, wywoła _int_malloc w arenie wątku.
__libc_malloc kod
```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>
Zauważ, że zawsze oznaczy zwrócony wskaźnik jako `tag_new_usable`, z kodu:
```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
To jest funkcja, która przydziela pamięć, używając innych pojemników i górnego kawałka.
Start
Zaczyna od zdefiniowania kilku zmiennych i uzyskania rzeczywistego rozmiaru, jaki potrzebuje żądana przestrzeń pamięci:
Fast Bin
Jeśli potrzebny rozmiar mieści się w rozmiarach Fast Bins, spróbuj użyć kawałka z fast bin. Zasadniczo, na podstawie rozmiaru, znajdzie indeks fast bin, w którym powinny znajdować się ważne kawałki, a jeśli jakieś istnieją, zwróci jeden z nich.
Ponadto, jeśli tcache jest włączone, napełni bin tcache tego rozmiaru kawałkami z fast bins.
Podczas wykonywania tych działań wykonywane są tutaj pewne kontrole bezpieczeństwa:
Jeśli kawałek jest źle wyrównany: malloc(): unaligned fastbin chunk detected 2
Jeśli kawałek do przodu jest źle wyrównany: malloc(): unaligned fastbin chunk detected
Jeśli zwrócony kawałek ma rozmiar, który nie jest poprawny z powodu swojego indeksu w fast bin: malloc(): memory corruption (fast)
Jeśli jakikolwiek kawałek użyty do napełnienia tcache jest źle wyrównany: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
Jeśli to nie był mały kawałek, to jest to duży kawałek, a w tym przypadku malloc_consolidate jest wywoływane, aby uniknąć fragmentacji pamięci.
Niezorganizowany bin
Czas sprawdzić niezorganizowany bin w poszukiwaniu potencjalnie ważnego kawałka do użycia.
Początek
Zaczyna się to od dużej pętli for, która będzie przeszukiwać niezorganizowany bin w kierunku bk, aż dotrze do końca (struktura arena) z while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
Ponadto, pewne kontrole bezpieczeństwa są przeprowadzane za każdym razem, gdy rozważany jest nowy kawałek:
Jeśli rozmiar kawałka jest dziwny (za mały lub za duży): malloc(): invalid size (unsorted)
Jeśli rozmiar następnego kawałka jest dziwny (za mały lub za duży): malloc(): invalid next size (unsorted)
Jeśli poprzedni rozmiar wskazany przez następny kawałek różni się od rozmiaru kawałka: malloc(): mismatching next->prev_size (unsorted)
Jeśli nie victim->bck->fd == victim lub nie victim->fd == av (arena): malloc(): unsorted double linked list corrupted
Ponieważ zawsze sprawdzamy ostatni, jego fd powinno zawsze wskazywać na strukturę arena.
Jeśli następny kawałek nie wskazuje, że poprzedni jest w użyciu: malloc(): invalid next->prev_inuse (unsorted)
Jeśli to się udało, zwróć kawałek i to koniec, jeśli nie, kontynuuj wykonywanie funkcji...
jeśli równa wielkość
Kontynuuj usuwanie kawałka z kosza, w przypadku gdy żądany rozmiar jest dokładnie taki sam jak rozmiar kawałka:
Jeśli tcache nie jest wypełniony, dodaj go do tcache i kontynuuj wskazując, że jest kawałek tcache, który można wykorzystać
Jeśli tcache jest pełne, po prostu go użyj, zwracając go
_int_malloc limity
W tym momencie, jeśli jakiś kawałek został przechowany w tcache, który można wykorzystać i limit został osiągnięty, po prostu zwróć kawałek z tcache.
Ponadto, jeśli MAX_ITERS został osiągnięty, przerwij pętlę i uzyskaj kawałek w inny sposób (kawałek górny).
Jeśli return_cached zostało ustawione, po prostu zwróć kawałek z tcache, aby uniknąć większych wyszukiwań.
Jeśli nie znaleziono odpowiedniego kawałka, kontynuuj
Duży kosz (następny większy)
Jeśli w dokładnym dużym koszu nie było żadnego kawałka, który mógłby być użyty, zacznij przeszukiwać wszystkie następne duże kosze (zaczynając od natychmiast większego), aż jeden zostanie znaleziony (jeśli w ogóle).
Reszta podzielonego kawałka jest dodawana do nieposortowanego kosza, last_reminder jest aktualizowany, a ta sama kontrola bezpieczeństwa jest przeprowadzana:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc start
Jeśli arena jest pusta lub żądany rozmiar jest zbyt duży (a pozostałe mmaps są dozwolone), użyj sysmalloc_mmap, aby przydzielić przestrzeń i ją zwrócić.
sysmalloc nie główna arena
Najpierw spróbuje rozszerzyć poprzedni stos dla tego stosu. Jeśli to nie będzie możliwe, spróbuje przydzielić nowy stos i zaktualizować wskaźniki, aby móc go używać.
Na koniec, jeśli to nie zadziała, spróbuje wywołać sysmalloc_mmap.
sysmalloc główny obszar poprzedni błąd 1
Jeśli poprzednie zwrócone MORECORE_FAILURE, spróbuj ponownie przydzielić pamięć używając sysmalloc_mmap_fallback
sysmalloc finale
Zakończ alokację, aktualizując informacje o arenie.
// 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;