(Nenhuma verificação é explicada neste resumo e alguns casos foram omitidos por brevidade)
__libc_malloc tenta obter um chunk do tcache, se não conseguir, chama _int_malloc
_int_malloc :
Tenta gerar a arena se não houver nenhuma
Se houver algum chunk de fast bin do tamanho correto, use-o
Preencha o tcache com outros chunks rápidos
Se houver algum chunk de small bin do tamanho correto, use-o
Preencha o tcache com outros chunks desse tamanho
Se o tamanho solicitado não for para small bins, consolide fast bin em unsorted bin
Verifique o unsorted bin, use o primeiro chunk com espaço suficiente
Se o chunk encontrado for maior, divida-o para retornar uma parte e adicione o restante de volta ao unsorted bin
Se um chunk for do mesmo tamanho que o tamanho solicitado, use-o para preencher o tcache em vez de retorná-lo (até que o tcache esteja cheio, então retorne o próximo)
Para cada chunk de tamanho menor verificado, coloque-o em seu respectivo small ou large bin
Verifique o large bin no índice do tamanho solicitado
Comece a procurar a partir do primeiro chunk que é maior que o tamanho solicitado, se algum for encontrado, retorne-o e adicione os restos ao small bin
Verifique os large bins a partir dos próximos índices até o final
A partir do próximo índice maior, verifique se há algum chunk, divida o primeiro chunk encontrado para usá-lo para o tamanho solicitado e adicione o restante ao unsorted bin
Se nada for encontrado nos bins anteriores, obtenha um chunk do top chunk
Se o top chunk não for grande o suficiente, amplie-o com sysmalloc
__libc_malloc
A função malloc na verdade chama __libc_malloc. Esta função verificará o tcache para ver se há algum chunk disponível do tamanho desejado. Se houver, usará; se não, verificará se é uma única thread e, nesse caso, chamará _int_malloc na arena principal, e se não, chamará _int_malloc na arena da thread.
Código __libc_malloc
```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>
Observe como ele sempre marcará o ponteiro retornado com `tag_new_usable`, do código:
```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
Esta é a função que aloca memória usando os outros bins e o top chunk.
Início
Ela começa definindo algumas variáveis e obtendo o tamanho real que o espaço de memória solicitado precisa ter:
Fast Bin
Se o tamanho necessário estiver dentro dos tamanhos dos Fast Bins, tente usar um chunk do fast bin. Basicamente, com base no tamanho, ele encontrará o índice do fast bin onde chunks válidos devem estar localizados e, se houver, retornará um deles.
Além disso, se o tcache estiver habilitado, ele preencherá o bin do tcache daquele tamanho com fast bins.
Enquanto realiza essas ações, algumas verificações de segurança são executadas aqui:
Se o chunk estiver desalinhado: malloc(): unaligned fastbin chunk detected 2
Se o chunk seguinte estiver desalinhado: malloc(): unaligned fastbin chunk detected
Se o chunk retornado tiver um tamanho que não está correto por causa de seu índice no fast bin: malloc(): memory corruption (fast)
Se algum chunk usado para preencher o tcache estiver desalinhado: malloc(): unaligned fastbin chunk detected 3
malloc_consolidate
Se não era um pequeno bloco, é um grande bloco, e neste caso malloc_consolidate é chamado para evitar a fragmentação de memória.
Bin não ordenado
É hora de verificar o bin não ordenado em busca de um chunk válido para usar.
Início
Isso começa com um grande loop for que irá percorrer o bin não ordenado na direção bk até chegar ao final (a estrutura da arena) com while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
Além disso, algumas verificações de segurança são realizadas toda vez que um novo chunk é considerado:
Se o tamanho do chunk é estranho (muito pequeno ou muito grande): malloc(): invalid size (unsorted)
Se o tamanho do próximo chunk é estranho (muito pequeno ou muito grande): malloc(): invalid next size (unsorted)
Se o tamanho anterior indicado pelo próximo chunk difere do tamanho do chunk: malloc(): mismatching next->prev_size (unsorted)
Se não victim->bck->fd == victim ou não victim->fd == av (arena): malloc(): unsorted double linked list corrupted
Como estamos sempre verificando o último, seu fd deve sempre apontar para a estrutura da arena.
Se o próximo chunk não indica que o anterior está em uso: malloc(): invalid next->prev_inuse (unsorted)
Se isso foi bem-sucedido, retorne o chunk e acabou, se não, continue executando a função...
se tamanho igual
Continue removendo o chunk do bin, caso o tamanho solicitado seja exatamente o do chunk:
Se o tcache não estiver cheio, adicione-o ao tcache e continue indicando que há um chunk de tcache que pode ser usado
Se o tcache estiver cheio, apenas use-o retornando-o
Limites do _int_malloc
Neste ponto, se algum chunk foi armazenado no tcache que pode ser usado e o limite é alcançado, apenas retorne um chunk do tcache.
Além disso, se MAX_ITERS for alcançado, saia do loop e obtenha um chunk de uma maneira diferente (top chunk).
Se return_cached foi definido, apenas retorne um chunk do tcache para evitar buscas maiores.
Se um chunk não for encontrado adequado para isso, continue
Grande Bin (próximo maior)
Se no grande bin exato não houver nenhum chunk que possa ser usado, comece a percorrer todos os próximos grandes bins (começando pelo imediatamente maior) até que um seja encontrado (se houver).
O restante do chunk dividido é adicionado no bin não ordenado, last_reminder é atualizado e a mesma verificação de segurança é realizada:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
sysmalloc início
Se a arena for nula ou o tamanho solicitado for muito grande (e houver mmaps permitidos restantes), use sysmalloc_mmap para alocar espaço e retorná-lo.
sysmalloc não é a arena principal
Ele tentará primeiro expandir o heap anterior para este heap. Se não for possível, tentará alocar um novo heap e atualizar os ponteiros para poder usá-lo.
Finalmente, se isso não funcionar, tente chamar sysmalloc_mmap.
sysmalloc main arena previous error 1
Se o anterior retornou MORECORE_FAILURE, tente novamente alocar memória usando sysmalloc_mmap_fallback
sysmalloc finale
Finalize a alocação atualizando as informações da 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;