Eu entendo que Rust não tem um coletor de lixo e estou me perguntando como a memória é liberada quando uma ligação sai do escopo.
Portanto, neste exemplo, entendo que Rust recupera a memória alocada para 'a' quando ele sai do escopo.
{
let a = 4
}
O problema que estou tendo com isso, em primeiro lugar, é como isso acontece e, em segundo lugar, isso não é uma espécie de coleta de lixo? Em que difere da coleta de lixo 'típica'?
Respostas:
A coleta de lixo é normalmente usada periodicamente ou sob demanda, como se o heap estiver quase cheio ou acima de algum limite. Em seguida, ele procura variáveis não utilizadas e libera sua memória, dependendo do algoritmo .
Rust saberia quando a variável sai do escopo ou seu tempo de vida termina no tempo de compilação e, portanto, inserir as instruções LLVM / assembly correspondentes para liberar a memória.
Rust também permite algum tipo de coleta de lixo, como a contagem de referência atômica .
fonte
new()
função ungida como C, elas são apenas funções estáticas e, em particular, algo comolet x = MyStruct::new()
cria seu objeto na pilha. O indicador real de alocação de heap éBox::new()
(ou qualquer uma das estruturas que dependem do Box).A ideia básica de gerenciar recursos (incluindo memória) em um programa, seja qual for a estratégia, é que os recursos vinculados a "objetos" inacessíveis podem ser recuperados. Além da memória, esses recursos podem ser bloqueios mutex, identificadores de arquivo, sockets, conexões de banco de dados ...
As linguagens com um coletor de lixo varrem periodicamente a memória (de uma forma ou de outra) para localizar objetos não usados, liberar os recursos associados a eles e, finalmente, liberar a memória usada por esses objetos.
Rust não tem GC, como funciona?
A ferrugem tem propriedade. Usando um sistema de tipo afim , ele rastreia qual variável ainda está segurando um objeto e, quando tal variável sai do escopo, chama seu destruidor. Você pode ver o sistema de tipo afim em vigor com bastante facilidade:
Rendimentos:
o que ilustra perfeitamente que em qualquer momento, no nível da linguagem, a propriedade é rastreada.
Esta propriedade funciona de forma recursiva: se você tem um
Vec<String>
(ou seja, uma matriz dinâmica de cordas), então cada umString
é de propriedade doVec
que em si é propriedade de uma variável ou um outro objeto, etc ... Assim, quando uma variável sai do escopo, ele libera recursivamente todos os recursos que mantinha, mesmo indiretamente. No caso deVec<String>
isso significa:String
Vec
próprioAssim, graças ao rastreamento de propriedade, o tempo de vida de TODOS os objetos do programa está estritamente ligado a uma (ou várias) variáveis de função, que acabarão por sair do escopo (quando o bloco ao qual eles pertencem terminar).
Nota: isso é um pouco otimista, usando a contagem de referências (
Rc
ouArc
) é possível formar ciclos de referências e assim causar vazamentos de memória, caso em que os recursos vinculados ao ciclo podem nunca ser liberados.fonte
Com uma linguagem em que você deve gerenciar manualmente a memória, a distinção entre a pilha e o heap torna-se crítica. Cada vez que você chama uma função, espaço suficiente é alocado na pilha para todas as variáveis contidas no escopo dessa função. Quando a função retorna, o quadro de pilha associado a essa função é "retirado" da pilha e a memória é liberada para uso futuro.
Do ponto de vista prático, esta limpeza de memória inadvertida é usada como um meio de armazenamento automático de memória que será apagado no final do escopo da função.
Há mais informações disponíveis aqui: https://doc.rust-lang.org/book/the-stack-and-the-heap.html
fonte