(Nessun controllo è spiegato in questo riepilogo e alcuni casi sono stati omessi per brevità)
__libc_malloc cerca di ottenere un chunk dal tcache, se non riesce chiama _int_malloc
_int_malloc :
Cerca di generare l'arena se non ce n'è una
Se c'è un chunk di fast bin della dimensione corretta, usalo
Riempie il tcache con altri chunk veloci
Se c'è un chunk di small bin della dimensione corretta, usalo
Riempie il tcache con altri chunk di quella dimensione
Se la dimensione richiesta non è per small bins, consolida il fast bin in unsorted bin
Controlla l'unsorted bin, usa il primo chunk con spazio sufficiente
Se il chunk trovato è più grande, dividilo per restituire una parte e aggiungi il resto all'unsorted bin
Se un chunk è della stessa dimensione della dimensione richiesta, usalo per riempire il tcache invece di restituirlo (fino a quando il tcache è pieno, poi restituisci il successivo)
Per ogni chunk di dimensione più piccola controllato, mettilo nel suo rispettivo small o large bin
Controlla il large bin nell'indice della dimensione richiesta
Inizia a cercare dal primo chunk che è più grande della dimensione richiesta, se ne trovi uno restituiscilo e aggiungi i resti al small bin
Controlla i large bins dagli indici successivi fino alla fine
Dal prossimo indice più grande controlla se ci sono chunk, dividi il primo chunk trovato per usarlo per la dimensione richiesta e aggiungi il resto all'unsorted bin
Se non viene trovato nulla nei bins precedenti, prendi un chunk dal top chunk
Se il top chunk non era abbastanza grande, ingrandiscilo con sysmalloc
__libc_malloc
La funzione malloc chiama effettivamente __libc_malloc. Questa funzione controllerà il tcache per vedere se c'è un chunk disponibile della dimensione desiderata. Se c'è, lo utilizzerà e se non c'è controllerà se è un singolo thread e in tal caso chiamerà _int_malloc nell'arena principale, e se non lo è chiamerà _int_malloc nell'arena del thread.
__libc_malloc codice
```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>
Nota come etichetterà sempre il puntatore restituito con `tag_new_usable`, dal codice:
```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
Questa è la funzione che alloca memoria utilizzando gli altri bin e il top chunk.
Inizio
Inizia definendo alcune variabili e ottenendo la dimensione reale che lo spazio di memoria richiesto deve avere:
Fast Bin
Se la dimensione necessaria è all'interno delle dimensioni dei Fast Bins, prova a utilizzare un chunk dal fast bin. Fondamentalmente, in base alla dimensione, troverà l'indice del fast bin dove dovrebbero trovarsi i chunk validi e, se presenti, restituirà uno di essi.
Inoltre, se tcache è abilitato, riempirà il tcache bin di quella dimensione con i fast bins.
Durante l'esecuzione di queste azioni, vengono eseguiti alcuni controlli di sicurezza:
Se il chunk è disallineato: malloc(): unaligned fastbin chunk detected 2
Se il chunk successivo è disallineato: malloc(): unaligned fastbin chunk detected
Se il chunk restituito ha una dimensione che non è corretta a causa del suo indice nel fast bin: malloc(): memory corruption (fast)
Se un chunk utilizzato per riempire il tcache è disallineato: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
Se non era un piccolo blocco, è un grande blocco, e in questo caso malloc_consolidate viene chiamato per evitare la frammentazione della memoria.
Unsorted bin
È tempo di controllare l'unsorted bin per un potenziale chunk valido da utilizzare.
Inizio
Questo inizia con un grande ciclo for che attraverserà l'unsorted bin nella direzione bk fino ad arrivare alla fine (la struttura arena) con while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
Inoltre, vengono eseguiti alcuni controlli di sicurezza ogni volta che un nuovo chunk viene considerato:
Se la dimensione del chunk è strana (troppo piccola o troppo grande): malloc(): invalid size (unsorted)
Se la dimensione del chunk successivo è strana (troppo piccola o troppo grande): malloc(): invalid next size (unsorted)
Se la dimensione precedente indicata dal chunk successivo differisce dalla dimensione del chunk: malloc(): mismatching next->prev_size (unsorted)
Se non victim->bck->fd == victim o non victim->fd == av (arena): malloc(): unsorted double linked list corrupted
Poiché stiamo sempre controllando l'ultimo, il suo fd dovrebbe sempre puntare alla struttura arena.
Se il chunk successivo non indica che il precedente è in uso: malloc(): invalid next->prev_inuse (unsorted)
Se questo ha avuto successo, restituisci il chunk e finisce qui, altrimenti continua a eseguire la funzione...
se dimensione uguale
Continua a rimuovere il chunk dal bin, nel caso in cui la dimensione richiesta sia esattamente quella del chunk:
Se il tcache non è pieno, aggiungilo al tcache e continua indicando che c'è un chunk tcache che potrebbe essere utilizzato
Se il tcache è pieno, usalo semplicemente restituendolo
_int_malloc limiti
A questo punto, se un chunk è stato memorizzato nel tcache che può essere utilizzato e il limite è stato raggiunto, basta restituire un chunk dal tcache.
Inoltre, se MAX_ITERS è stato raggiunto, esci dal ciclo e ottieni un chunk in un modo diverso (top chunk).
Se return_cached è stato impostato, basta restituire un chunk dal tcache per evitare ricerche più ampie.
Se un chunk non è trovato adatto per questo, continua
Large Bin (prossimo più grande)
Se nel large bin esatto non c'era alcun chunk che potesse essere utilizzato, inizia a scorrere tutti i successivi large bin (partendo da quello immediatamente più grande) fino a trovarne uno (se presente).
Il resto del chunk diviso viene aggiunto nel bin non ordinato, last_reminder viene aggiornato e viene eseguita la stessa verifica di sicurezza:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc inizio
Se l'arena è nulla o la dimensione richiesta è troppo grande (e ci sono mmaps permessi rimasti) usa sysmalloc_mmap per allocare spazio e restituirlo.
sysmalloc non main arena
Prima cercherà di estendere l'heap precedente per questo heap. Se non è possibile, cercherà di allocare un nuovo heap e aggiornare i puntatori per poterlo utilizzare.
Infine, se non ha funzionato, proverà a chiamare sysmalloc_mmap.
sysmalloc main arena previous error 1
Se il precedente ha restituito MORECORE_FAILURE, prova di nuovo ad allocare memoria usando sysmalloc_mmap_fallback
sysmalloc finale
Completa l'allocazione aggiornando le informazioni dell'arena.
// 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;