2011-01-12 7 views
5

Aunque creo que entiendo la esencia del problema (es decir, un buen GC rastrea objetos, no ámbito), no sé lo suficiente sobre el tema para convencer a los demás.¿Por qué la RAII y la recolección de basura son mutuamente excluyentes?

¿Puede darme una explicación de por qué no hay lenguajes recogidos de basura con destructores deterministas?

+0

-1 La pregunta es incorrecta. Hay lenguajes recogidos de basura con destructores deterministas, p. 'IDisposable' en .NET proporciona destrucción determinista para C#, VB.NET y F #. –

Respuesta

3

NO son mutuamente excluyentes. Siéntase libre de usar C++ con libgc (recopilador Boehm-Reiser-Detlefs). Todavía puede usar RAII, punteros inteligentes y eliminación manual, pero con el GC funcionando también puede simplemente "olvidarse" de eliminar algunos objetos.

@ La respuesta de Andy con respecto a que los recursos se eliminan demasiado tarde pierde de vista el punto importante: no es la demora la liberación de recursos lo que es crucial semánticamente, sino más bien el orden de liberación.

La razón por la que GC tiende a no ordenar bien la liberación es que requeriría una clasificación topológica en los requisitos de pedido (dependencias) y eso es un algoritmo costoso.

Sin embargo, Ocaml GC tiene una instalación interesante donde puede conectar un finalizador a un objeto. Si el objeto se vuelve inalcanzable, se ejecuta el finalizador, sin embargo, el objeto no se elimina (porque el finalizador podría hacerlo accesible de nuevo: en ese caso, puede adjuntar otro finalizador). Estos finalizadores pueden proporcionar cierto control sobre los pedidos.

+0

El orden de publicación puede ser importante. Pero también puede ser importante un retraso indefinido para su publicación y una posible falla completa en la publicación. No es ninguno de los dos, o son ambos. –

+0

¡De hecho, un retraso indefinido para la liberación puede ser importante, que incluye la liberación de la memoria! El rendimiento importa Pero no es relevante semánticamente. Sin embargo, la falla completa de liberación sí importa, pero no puede suceder si el GC se ejecuta en el punto de terminación. Para algunos recursos, como los identificadores de archivos en Unix, uno tiende a no ejecutar el GC en la terminación porque el sistema operativo liberará los recursos de todos modos. El consejo general que usa un GC es NO usar RAII para recursos críticos, liberarlo bajo el control del programa. Sin embargo, no está claro lo que eso significa con la evaluación perezosa, por ejemplo, en Haskell. – Yttrill

0

De Wikipedia, tras señalar que el seguimiento de los recolectores de basura son el tipo más común:

Rastreo de recolección de basura no es determinista. Un objeto que se convierta en elegible para la recolección de basura se generalmente se limpiará eventualmente, pero no hay garantía cuando (o incluso si) eso sucederá.

Por lo tanto, confiar en RAII podría hacer que el recurso se elimine demasiado tarde.

Como resultado, por ejemplo, Java tiene una guía para "evitar finalizadores" (Punto 6 en "Java efectivo" por Josua Bloch). "Nunca se debe hacer nada crítico en el tiempo en un finalizador".

+0

FWIW La página de Wikipedia sobre la recolección de basura está mal, incluida esa sección. –

+0

@JonHarrop - Cualquier crítica específica a esta respuesta es bienvenida. –

+0

Está claro que la acción de un algoritmo simple de GC es completamente determinista en una única aplicación de subprocesos. Puede o no ser difícil de predecir, pero mi sistema al menos tiene una llamada collect() explícita que ejecuta el GC y ejecutará los finalizadores. El determinismo solo se pierde en las aplicaciones de subprocesos múltiples, que pueden tener determinismo acotado o ilimitado de todos modos (dependiendo del sistema y la aplicación), por lo que no está claro que incluso en ese caso un GC empeore las cosas de lo que ya son. – Yttrill

0

El recolector de basura no puede ejecutarse todo el tiempo (el recuento se acerca, pero generalmente no cuenta como recolección de basura), por lo que ni siquiera lo intenta. No es práctico. Por lo tanto, hay un retraso inevitable entre un objeto que se vuelve inalcanzable (por ejemplo, porque la única referencia sale del alcance) y el GC lo recoge, posiblemente disparando un finalizador. Este retraso no es determinista ... a menos que (y luego, la destrucción determinista en el sentido más estricto de la palabra sea posible, aunque todavía no sea práctico) forzar al CG a un cronograma determinista, pero esto se acerca mucho a "GC funcionando todo el tiempo" , que aún es increíblemente poco práctico.

Por lo tanto, la GC y la limpieza determinista son mutuamente excluyentes porque el GC hace toda la limpieza y no puede permitirse ser determinista, pero debe confiar en maximizar su eficiencia.

Cuestiones relacionadas