O que é o Heap? Memória para dados de vida longa
O heap é uma região de memória para dados cujo tamanho ou tempo de vida não é conhecido de antemão, alocada sob demanda e liberada manualmente ou por um garbage collector.
Quando os dados precisam sobreviver à função que os criou, ou quando seu tamanho é decidido em runtime, eles vão para o heap em vez do stack. A alocação no heap é mais flexível que a do stack, porém mais lenta, e a memória não é recuperada automaticamente quando uma função retorna. Ou você a libera, ou um garbage collector o faz.
Para que serve o heap
O heap guarda objetos, arrays e estruturas cujo tamanho é dinâmico ou cujo tempo de vida abrange muitas chamadas de função. Você solicita um bloco, o usa pelo tempo necessário e o libera quando termina, diretamente ou via garbage collection.
Heap vs stack
O stack é rápido, de tamanho fixo e limpo automaticamente no retorno; o heap é flexível, grande e precisa ser gerenciado. Dados do stack morrem com sua função; dados do heap vivem até serem liberados ou coletados, e é por isso que estado de vida longa pertence ao heap.
Como a memória do heap é gerenciada
- Manual: alocar e liberar explicitamente, como em C com malloc e free.
- Garbage-collected: o runtime recupera objetos inalcançáveis automaticamente.
- Reference-counted: a memória é liberada quando a última referência desaparece.
- Pool ou arena: blocos agrupados e liberados juntos por velocidade.
Problemas de heap para observar
Como a memória do heap não é liberada automaticamente, é nela que os leaks se acumulam e onde a fragmentação torna a alocação mais lenta com o tempo. É também a memória com maior probabilidade de esgotar e disparar condições de out-of-memory.
Um exemplo rápido
Criar uma lista grande que você retorna de uma função e continua usando em outro lugar significa que esses dados vivem no heap; eles persistem depois de a função retornar, ao contrário de um local que sumiria do stack.
O heap no CI
O uso de heap é do que trata a maioria das falhas de out-of-memory no CI: um build ou test run aloca mais heap do que o runner permite e é morto. Runners maiores (Latchkey) elevam o teto, e OOM kills transitórios podem ter retry automático, embora um leak real ainda precise de correção.
Principais conclusões
- O heap armazena dados de tamanho dinâmico e vida longa, alocados sob demanda.
- É flexível, mas mais lento que o stack e não é liberado automaticamente no retorno da função.
- O esgotamento do heap está por trás da maioria das falhas de out-of-memory no CI.