Suponha que você tenha alguma linguagem de programação com gerenciamento manual de memória. Quais recursos essa linguagem precisa para poder implementar a coleta de lixo precisa como uma biblioteca e não como uma construção fundamental da linguagem?
Por um GC preciso, quero dizer um em que apenas ponteiros para a pilha são percorridos para verificar quais variáveis estão ou não estão ativas.
Algumas considerações adicionais:
- C e C ++ têm o coletor de lixo Boehm, mas não conto isso, já que não é um GC preciso. O coletor Boehm assume que qualquer coisa na pilha que possa ser um ponteiro, com base puramente nos requisitos de alinhamento de memória, é um ponteiro. Por exemplo, qualquer número inteiro
k
que(k % 4) == 0
pareça um nível de bit como um ponteiro, pois os ponteiros devem estar alinhados em 4 bytes. - o pega transforma o código C existente para usar um coletor de lixo preciso. O código C gerado possui muitos stubs para coleta de lixo, ou seja, material para registrar qualquer ponteiro de pilha na pilha com o coletor. Não conto isso porque ninguém poderia escrever código dessa maneira; é mais um destino de compilação para outros idiomas.
Eu imagino que essa linguagem precisaria ter:
- Macros ou alguma forma de metaprogramação, para encapsular todo o código extra necessário para fazer coisas como registrar raízes de GC.
- Algum mecanismo reflexivo que permite inspecionar estruturas ou uniões; você precisa determinar quais membros são ponteiros.
- Algum mecanismo reflexivo que permite examinar o layout do quadro da pilha. Isso soa muito mais difícil que 2.
Espero que isso não seja muito vago ou baseado em opiniões, mas estou pensando nisso há algum tempo.
Respostas:
Acredito que isso seja possível, ou pelo menos quase possível, em uma linguagem como Rust, embora talvez não necessariamente no sentido em que você está pensando.
Rust realmente tem uma biblioteca de GC , embora eu não possa dizer o quão preciso é. Mas a ideia é que existe um tipo específico
Gc<T>
para ponteiros coletados de lixo para valores do tipoT
. Portanto, a metaprogramação que você está falando não aconteceO que torna possível que isso seja preciso é o sistema de propriedade da Rust: por causa da digitação linear afim, todo local na memória tem no máximo um ponteiro para ele, a menos que seja declarado usando um
unsafe
bloco (que é usado para implementar coisas como o coletor de lixo) . Portanto, se você tiver um ponteiro que não esteja envolvido em umGc
tipo, ele será desalocado assim que sair do escopo. Portanto, não é possível considerar algo como um ponteiro que não seja: ele está envolvido noGc
tipo ou é de propriedade individual e desalocado automaticamente.Todo tipo tem um
drop
método implícito chamado quando sai do escopo, que desaloca as coisas para as quais aponta. Estedrop
método está ciente do que é e do que não é um ponteiro, o que também ajuda com precisão.O idioma é fortemente digitado estaticamente e, a menos que você esteja especificamente em um
unsafe
bloco, não é possível converter as coisas para outros tipos, para que seja sabido estaticamente qual o tipo de um determinado pedaço de memória.Este não é um transformador drop-in que permite tratar o código que não é GC como lixo coletado. O programador especifica especificamente quais valores são coletados. Mas, considerando isso, acho que tem o potencial de atender aos seus critérios.
fonte
Eu acho que é possível implementar um coletor de lixo em C ++ sem alterar a própria linguagem. Mas, para usar o coletor de lixo, é preciso restringir o programador de usar construções de linguagem arbitrárias. Em particular, todas as solicitações de alocação de memória devem ser feitas através das APIs de alocação fornecidas pelo coletor de lixo e todo o acesso deve ser feito através de referências gerenciadas pelo coletor de lixo.
fonte