Um coletor de lixo (GC) é um gerenciador de memória. Muitas linguagens de programação têm um GC embutido. Esse recurso aloca e desaloca automaticamente a memória em um programa. Ele libera memória vinculada e não utilizada que torna seu aplicativo mais lento.

A beleza de um GC é que ele libera memória em seu nome, sem que você precise fazer nada. Você pode, portanto, considerá-lo um recurso tão essencial que espera que todas as linguagens de programação o tenham. Infelizmente, este não é o caso; mesmo uma linguagem popular como C pode não ter um GC.

Como funciona a alocação de memória?

Quando você executa um programa em qualquer linguagem de programação, seu sistema operacional reserva um pilha de dados na memória para aquele programa. Este programa possui e ocupa esta pilha de dados até completar a execução. Se o seu programa precisar de mais memória do que a disponível, ele poderá alocar dinamicamente mais memória do heap de memória do sistema operacional.

Na programação, uma variável representa um local de memória. Assim, quando você declara uma nova variável, a linguagem de programação aloca espaço na memória para essa variável. A variável agora terá um endereço de memória. Até que você atribua um valor a essa variável, ela permanecerá não inicializada e poderá conter algum valor lixo.

instagram viewer

Se uma linguagem de programação permite declarar uma variável sem inicializá-la, ela é uma variável dinâmica. Isso significa que o valor que você atribui à variável pode mudar com o tempo. No entanto, a localização de memória da variável permanecerá a mesma até que você a desaloque.

Como funciona a desalocação de memória?

A alocação de memória é um processo semelhante para todas as linguagens de programação. Mas o método correspondente de desalocação de memória tende a diferir. Existem dois tipos de métodos de desalocação de memória; manuais e automáticos. Um GC faz a desalocação automática.

Desalocação de memória sem um coletor de lixo

o linguagem de programação C não usa um GC para desalocação de memória. Portanto, os programadores C devem alocar e desalocar manualmente a memória. C permite alocação dinâmica de memória para quando você não sabe, em tempo de compilação, quanta memória você usará em tempo de execução.

A biblioteca padrão (stdlib.h) contém as funções que C usa para gerenciar a alocação dinâmica de memória. Essas funções incluem:

  • malloc(): aloca um tamanho específico de memória e retorna um ponteiro para essa memória. Se não houver memória suficiente disponível no pool de memória do sistema operacional, ele retornará nulo.
  • free(): desaloca um bloco específico de memória e o retorna ao pool de memória do sistema operacional.

Exemplo de programa C

#incluir
#incluir

inta Principal()
{
int *pt; // declara ponteiro
int j; // declara contador

// aloca espaço para 200 inteiros
ptr = (int *) malloc(200 * tamanho de(int));

// insere valores inteiros na memória alocada
// e imprime cada valor no console
por (j = 0; j< 200; j++)
{
ptr[j] = j;
printf("%d\t",ptr[j]);
}

//desaloca a memória alocada anteriormente
gratuitamente(ptr);
Retorna0;
}

O código acima aloca memória para armazenar 200 valores inteiros usando o malloc() função. Ele usa um ponteiro para acessar esse local de memória e armazena 200 valores inteiros nele. O ponteiro também imprime os dados armazenados no local da memória no console. Finalmente, o programa desaloca a memória previamente alocada usando o gratuitamente() função.

Desalocação de memória com um coletor de lixo

Várias linguagens de programação populares usam um GC para gerenciamento de memória. Isso facilita muito a vida dos programadores que usam essas linguagens. C# e Java são duas linguagens de programação que usam um GC.

O C# GC

No linguagem de programação C#, um GC gerencia a alocação e desalocação de endereços de memória. Portanto, um programador C# não precisa se preocupar em desalocar um objeto depois de concluir sua finalidade.

O C# GC inicializa um pool de memória, chamado de heap gerenciado, para cada novo processo (ou programa). Ele chama o VirtualAlloc() função para alocar memória e o VirtualFree() função para desalocá-lo. A melhor parte é que tudo isso acontece em segundo plano, sem nenhum esforço de você, o programador.

O C# GC tem um mecanismo de otimização, que ele usa para decidir quando desalocar memória. O mecanismo de otimização examina a raiz do aplicativo para determinar quais objetos não estão mais em uso. Ele faz isso criando um gráfico que se estende desde a raiz do aplicativo até os objetos conectados. Esta raiz inclui campos estáticos, variáveis ​​locais, etc. Qualquer objeto não conectado à raiz do aplicativo é lixo.

O mecanismo de otimização do GC não apenas coleta memória por conta própria. Deve haver primeiro uma nova solicitação de alocação de memória. Se o sistema tiver pouca memória disponível, o mecanismo de otimização do GC entrará em ação.

O Java GC

Em Java, um GC também gerencia a alocação e desalocação de endereços de memória. No entanto, o Java atualmente tem quatro tipos diferentes de coletores de lixo suportados:

  • Lixo-Primeiro (G1)
  • Serial
  • Paralelo
  • Z Coletor de Lixo (ZGC)

O coletor de lixo G1 é o GC padrão do Java desde o lançamento do Java Development Kit (JDK) 9. Java organiza dados em objetos e armazena esses objetos em um heap de tamanho fixo. O coletor de lixo G1 divide o heap em regiões de heap de tamanho igual. Em seguida, ele dividiu essas regiões de heap em duas seções; gerações jovens e velhas.

Cada vez que você cria um novo objeto, a alocação de espaço para esse objeto acontece na geração jovem. Usando um processo de envelhecimento, o coletor de lixo G1 copia objetos nas regiões jovens para as regiões antigas. Ele também copia objetos que já estão na região antiga para uma região mais antiga.

O coletor de lixo G1 então executa a maior parte de sua desalocação de memória na geração jovem, ocasionalmente se aventurando na seção da geração antiga.

Quais são os benefícios de ter um coletor de lixo?

O benefício de ter um coletor de lixo é que ele impede que você pense no gerenciamento de memória enquanto escreve seu código. Isso lhe dá tempo para se concentrar em outros aspectos importantes de sua aplicação. No entanto, vários outros benefícios merecem destaque.

Recuperar objetos não utilizados e liberar memória fornece uma execução mais limpa do aplicativo. Se o seu programa liberar memória o mais rápido possível, ele terá uma pegada de memória menor e poderá ser executado com mais eficiência.

A coleta de lixo reduz os erros relacionados ao gerenciamento de memória, como vazamentos e erros de ponteiro. Isso ocorre porque o processo não depende mais do programador e de sua capacidade de escrever código preciso.