Supongamos que tiene un lenguaje de programación con administración de memoria manual. ¿Qué características necesita tener este lenguaje para poder implementar la recolección de basura precisa como una biblioteca, y no como una construcción de lenguaje fundamental?
Por GC preciso me refiero a uno en el que solo se atraviesan punteros al montón para determinar qué variables están o no en vivo.
Algunas consideraciones adicionales:
- C y C ++ tienen el recolector de basura Boehm, pero no cuento esto ya que no es un GC preciso. El recopilador de Boehm supone que cualquier cosa en la pila que pueda ser un puntero, basado únicamente en los requisitos de alineación de memoria, es un puntero. Por ejemplo, cualquier número entero
k
que(k % 4) == 0
parezca un nivel de bit como un puntero, ya que los punteros deben estar alineados en 4 bytes. - Urraca transforma el código C existente para utilizar un recolector de basura preciso. El código C generado tiene muchos apéndices para la recolección de basura, es decir, cosas para registrar cualquier puntero de pila en el montón con el recolector. No cuento esto porque nunca se podría esperar que nadie escriba código de esa manera; Es más un objetivo de compilación para otros idiomas.
Me imagino que ese lenguaje debería tener:
- Macros o alguna forma de metaprogramación, para encapsular todo el código adicional necesario para hacer cosas como registrar raíces GC.
- Algún mecanismo reflexivo que le permite inspeccionar estructuras o uniones; debe determinar qué miembros son punteros.
- Algún mecanismo reflexivo que le permite examinar el diseño del marco de la pila. Esto suena mucho más difícil que 2.
Espero que esto no sea demasiado vago o basado en opiniones, pero me he estado preguntando por un tiempo.
Respuestas:
Creo que esto es posible, o al menos casi posible, en un lenguaje como Rust, aunque tal vez no necesariamente en el sentido en que está pensando.
Rust en realidad tiene una biblioteca GC , aunque no puedo decir qué tan precisa es. Pero la idea es que hay un tipo específico
Gc<T>
para punteros recolectados de basura a valores de tipoT
. Entonces la metaprogramación de la que estás hablando no sucedeLo que hace posible que esto sea preciso es el sistema de propiedad de Rust: debido a la tipificación lineal afinada, cada ubicación en la memoria tiene como máximo un puntero, a menos que se declare que usa un
unsafe
bloque (que se usa para implementar cosas como el recolector de basura) . Entonces, si tiene un puntero que no está envuelto en unGc
tipo, se desasigna tan pronto como sale del alcance. Por lo tanto, no es posible considerar algo como un puntero que no lo es: está envuelto en elGc
tipo o es de propiedad individual y se desasigna automáticamente.Cada tipo tiene un
drop
método implícito que se llama cuando está fuera de alcance, que desasigna las cosas a las que apunta. Estedrop
método es consciente de lo que es y no es un puntero, lo que también ayuda con precisión.El lenguaje está fuertemente, estáticamente tipado, y a menos que esté específicamente en un
unsafe
bloque, no puede transmitir cosas a otros tipos, por lo que se puede saber estáticamente qué tipo tiene un trozo de memoria dado.Este no es un transformador directo que le permite tratar el código no GC como basura recolectada. El programador especifica específicamente qué valores se recopilan. Pero dado eso, creo que tiene el potencial para cumplir con sus criterios.
fuente
Creo que es posible implementar un recolector de basura en C ++ sin cambiar el lenguaje en sí. Pero para usar el recolector de basura, uno debe restringir que el programador use construcciones de lenguaje arbitrarias. En particular, todas las solicitudes de asignación de memoria deben realizarse a través de las API de asignación proporcionadas por el recolector de elementos no utilizados, y todo el acceso debe realizarse a través de referencias administradas por el recolector de elementos no utilizados.
fuente