c# - tirar - ¿Cuáles de estos objetos son elegibles para la recolección de basura?
servicio de recolección de basura (4)
Esta es una pregunta que me formularon recientemente en mi entrevista: ¿Qué objeto (s) ''aleatorio'' se recopilarían durante la llamada ''GC.Collect ()''?
String a = new Random().Next(0, 1) ==1 ? "Whatever 1" : "Whatever 2";
String b = new WeakReference(new Random()).Target.Next(0, 1) == 1 ?
"Whatever 1" : "Whatever 2";
GC.Collect();
Respondí que esta es una pregunta específica de la implementación y depende en gran medida de la implementación del GC
y la correspondiente semántica de referencia débil. Hasta donde yo sé, la especificación C # no proporciona una descripción exacta de lo que debe hacer GC.Collect
y cómo deben manejarse las referencias débiles.
Sin embargo, mi entrevistador quería escuchar algo más.
Ambas instancias Random()
y WeakReference
son elegibles para la recopilación:
- El primer
Random
no se almacenó en un local, y mucho menos en un local que luego se lee. - El segundo
Random
se pasó aWeakReference
, por lo que estaría bien recopilar de todos modos , peroWeakReference
sí no se realiza en ningún lado, por lo que también es elegible para la recopilación.
Ninguna de las cadenas son (solo hay 2 instancias de cadena aquí, no 4, incluso si se alcanzó cada posible ruta de código): como son literales en el código c #, se internan una vez que existen.
Es cierto que esto depende de la implementación (y del compilador). Si todo esto está en el mismo método, no puede saber qué objetos están todavía en la pila . Ya que los objetos en la pila todavía se referencian no serían coleccionables.
Lo que el entrevistador más deseaba que hiciera es verificar qué objetos son aún accesibles a la llamada de GC. Recoja asumiendo una implementación "perfecta" que lo descarte todo lo antes posible.
GC.Collect es como en Java equivalente a System.gc ()
"Recomienda" verificar valores nulos para eliminarlos. Realmente no se puede depender de esta característica ya que es muy automática a diferencia de C ++.
¡Espero eso ayude!
Sin embargo, mi entrevistador quería escuchar algo más.
Espero que quieran escuchar una respuesta como la que Marc Gravell ha publicado aquí, pero que se basa en un modelo demasiado simplificado de cómo funcionan las máquinas virtuales recolectadas con basura que no se parecen a la realidad.
Por ejemplo, la llamada a GC.Collect
podría optimizar el GC.Collect
llamada, en cuyo caso no hay raíces globales, por lo que todos los bloques asignados al montón se recopilan. O el compilador puede crear una nueva entrada en el marco de la pila para cada elemento temporal (no solo las variables en el código fuente) que mantiene todo accesible y no se recoge nada. O el compilador puede intercambiar el orden de la creación de las cadenas a
y b
y recoger el objeto Random
referido por WeakReference
antes de WeakReference
el método Target
causando una excepción de referencia null
para que el otro Random
nunca se asigne.