Abordagens para Gerenciamento de Memória

Tradicionalmente, as linguagens se dividem em duas grandes categorias:

  • Controle total através do gerenciamento manual de memória: C, C++, Pascal, ...
    • Programador decide quando alocar ou liberar memória do heap.
    • Programador deve determinar se um ponteiro ainda aponta para uma memória válida.
    • Estudos mostram que os programadores cometem erros.
  • Segurança total através do gerenciamento automático de memória em tempo de execução: Java, Python, Go, Haskell, ...
    • Um sistema em tempo de execução garante que a memória não seja liberada até que não possa mais ser referenciada.
    • Normalmente implementado com contagem de referência, coleta de lixo ou RAII.

Rust oferece uma nova combinação:

Controle total e segurança por imposição do correto gerenciamento de memória em tempo de compilação.

Ele faz isso com um conceito de ownership (posse) explícito.

This slide should take about 10 minutes.

Este slide tem a intenção de ajudar os alunos que vêm de outras linguagens a colocar o Rust em contexto.

  • Em C, o gerenciamento do heap é feito manualmente com malloc e free. Os erros comuns incluem esquecer de chamar free, chamá-lo várias vezes para o mesmo ponteiro ou desreferenciar um ponteiro depois que a memória para a qual ele aponta foi liberada.

  • O C++ possui ferramentas como ponteiros inteligentes (unique_ptr, shared_ptr) que aproveitam as garantias da linguagem sobre a chamada de destrutores para garantir que a memória seja liberada quando uma função retorna. Ainda é muito fácil usar essas ferramentas de maneira incorreta e criar bugs semelhantes aos do C.

  • Java, Go e Python dependem do coletor de lixo para identificar a memória que não é mais acessível e descartá-la. Isso garante que qualquer ponteiro possa ser desreferenciado, eliminando o uso após a liberação e outras classes de bugs. Mas, o coletor de lixo tem um custo de tempo de execução e é difícil de ajustar corretamente.

O modelo de ownership e borrowing do Rust pode, em muitos casos, obter o desempenho do C, com operações de alocação e liberação precisamente onde elas são necessárias - custo zero. Ele também fornece ferramentas semelhantes aos ponteiros inteligentes do C++. Quando necessário, outras opções, como contagem de referência, estão disponíveis, e até mesmo crates de terceiros estão disponíveis para suportar a coleta de lixo em tempo de execução (não abordada nesta aula).