(Nenhuma verificação é explicada neste resumo e alguns casos foram omitidos por brevidade)
__libc_malloc tenta obter um bloco do tcache, se não conseguir, chama _int_malloc
_int_malloc :
Tenta gerar a arena se não houver nenhuma
Se houver algum bloco de fast bin do tamanho correto, use-o
Preenche o tcache com outros blocos de fast bin
Se houver algum bloco de small bin do tamanho correto, use-o
Preenche o tcache com outros blocos desse tamanho
Se o tamanho solicitado não for para small bins, consolida fast bin em unsorted bin
Verifica o unsorted bin, usa o primeiro bloco com espaço suficiente
Se o bloco encontrado for maior, divida-o para retornar uma parte e adicione o restante de volta ao unsorted bin
Se um bloco for do mesmo tamanho que o 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 bloco de tamanho menor verificado, coloque-o no seu respectivo small ou large bin
Verifica o large bin no índice do tamanho solicitado
Comece a procurar a partir do primeiro bloco que seja maior que o tamanho solicitado, se encontrar algum, retorne-o e adicione os restos ao small bin
Verifica os large bins dos próximos índices até o final
Do próximo índice maior, verifique se há algum bloco, divida o primeiro bloco encontrado para usá-lo para o tamanho solicitado e adicione o restante ao unsorted bin
Se nada for encontrado nos bins anteriores, obtenha um bloco do bloco superior
Se o bloco superior não for grande o suficiente, aumente-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 bloco disponível do tamanho desejado. Se houver, ele o usará e, se não houver, 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`, a partir 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 bloco superior.
Início
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 pedaço do fast bin. Basicamente, com base no tamanho, ele encontrará o índice do fast bin onde os pedaços válidos devem estar localizados e, se houver algum, retornará um deles.
Além disso, se o tcache estiver ativado, ele preencherá o tcache bin desse tamanho com fast bins.
Enquanto realiza essas ações, algumas verificações de segurança são executadas aqui:
Se o pedaço estiver desalinhado: malloc(): pedaço fastbin desalinhado detectado 2
Se o pedaço à frente estiver desalinhado: malloc(): pedaço fastbin desalinhado detectado
Se o pedaço retornado tiver um tamanho incorreto por causa de seu índice no fast bin: malloc(): corrupção de memória (fast)
Se algum pedaço usado para preencher o tcache estiver desalinhado: malloc(): pedaço fastbin desalinhado detectado 3
malloc_consolidate
Se não era um pequeno pedaço, é um grande pedaço e, nesse caso, malloc_consolidate é chamado para evitar fragmentação de memória.
Bin não ordenado
É hora de verificar o bin não ordenado em busca de um possível chunk válido para usar.
Início
Isso começa com um grande loop que 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 sempre que um novo chunk é considerado:
Se o tamanho do chunk for estranho (muito pequeno ou muito grande): malloc(): tamanho inválido (não ordenado)
Se o tamanho do próximo chunk for estranho (muito pequeno ou muito grande): malloc(): tamanho próximo inválido (não ordenado)
Se o tamanho anterior indicado pelo próximo chunk difere do tamanho do chunk: malloc(): next->prev_size incompatível (não ordenado)
Se não victim->bck->fd == victim ou não victim->fd == av (arena): malloc(): lista duplamente encadeada não ordenada corrompida
Como estamos sempre verificando o último, seu fd deve estar sempre apontando para a estrutura da arena.
Se o próximo chunk não estiver indicando que o anterior está em uso: malloc(): next->prev_inuse inválido (não ordenado)
Se isso foi bem-sucedido, retorne o chunk e acabou, caso contrário, continue executando a função...
se o tamanho for igual
Continue removendo o chunk do bin, no caso em que o tamanho solicitado é exatamente o mesmo do chunk:
Se o tcache não estiver cheio, adicione-o ao tcache e continue indicando que há um chunk de tcache que poderia ser usado
Se o tcache estiver cheio, simplesmente use-o retornando-o
Limites do _int_malloc
Neste ponto, se algum bloco foi armazenado no tcache que pode ser usado e o limite é atingido, apenas retorne um bloco tcache.
Além disso, se MAX_ITERS for atingido, saia do loop e obtenha um bloco de uma maneira diferente (bloco superior).
Se return_cached foi definido, apenas retorne um bloco do tcache para evitar buscas maiores.
Se um chunk não for encontrado adequado para isso, continue
Large Bin (próximo maior)
Se na large bin exata não houver nenhum chunk que possa ser usado, comece a percorrer todas as próximas large bins (começando pela imediatamente maior) até que uma seja encontrada (se houver).
O restante do chunk dividido é adicionado na unsorted bin, last_reminder é atualizado e a mesma verificação de segurança é realizada:
bck->fd-> bk != bck: malloc(): corrupted unsorted chunks2
sysmalloc
Início do sysmalloc
Se a arena for nula ou o tamanho solicitado for muito grande (e ainda houver mmaps permitidos), use sysmalloc_mmap para alocar espaço e retorná-lo.
sysmalloc não é a arena principal
Primeiro tentará 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.
Por fim, se isso não funcionar, tentará chamar sysmalloc_mmap.
sysmalloc final
Conclua 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;