2011-11-19 13 views
12

Esta es una pregunta que me formularon recientemente en mi entrevista: ¿Qué objeto (s) 'aleatorio' se recopilarían durante la llamada 'GC.Collect()'?¿Cuáles de estos objetos son elegibles para la recolección de basura?

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 se trata de una cuestión específica de la implementación y depende en gran medida de la aplicación GC y las correspondientes semántica de referencia débiles. Hasta donde yo sé, la especificación C# no proporciona una descripción exacta de lo que GC.Collect debería hacer y cómo deberían manejarse las referencias débiles.

Sin embargo, mi entrevistador quería escuchar algo más.

+3

Fuiste muy educado. Mi respuesta sería si hay algo terriblemente mal ... –

+0

sería genial si la etiqueta 'Java' también se agrega a esta pregunta. – Bhushan

Respuesta

13

Ambos Random() instancias y la WeakReference son elegibles para la recolección:

  • La primera Random no se almacenó en un local, y mucho menos un local que se lee más adelante.
  • El segundo Random se hizo pasar a un WeakReference, por lo que estaría bien para recoger todos modos, pero el WeakReference en sí no se mantiene en cualquier lugar, por lo que también es elegible para la colección.

Ninguna de las cadenas son (hay solo 2 instancias de cadena aquí, no 4, incluso si se alcanzó cada ruta de código posible): porque son literales en el código C#, se internan una vez que existen.

+0

Sí, obviamente, la pregunta era sobre los objetos 'Aleatorios', lo siento, me olvidé de mencionar eso. –

+0

Ahora, ¿se puede decir que mi respuesta es incorrecta y es la respuesta correcta que ** ambos son? ** –

+0

Sí; clarificado: consulte la actualización –

9

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 quería que hiciera es verificar qué objetos son todavía accesibles a la llamada de GC. Recoja asumiendo una implementación "perfecta" que lo descarte todo lo antes posible.

+0

¿Por qué el voto a favor? Esto es importante para saber cuándo se codifican las pruebas unitarias que involucran el comportamiento del GC, estoy hablando de falta de experiencia aquí. Expliqué explícitamente una diferencia entre lo que el entrevistador probablemente quería escuchar y cuál es la realidad técnica. – Zarat

+0

+1 por ser la primera respuesta correcta que he leído. "asumiendo una implementación perfecta". Dado que la pregunta es absurda, me abstendría de especular acerca de lo que el entrevistador pensaba que estaban haciendo. –

1

GC.Collect es como en Java equivalente a System.gc()

Es "recomienda" para comprobar si hay valores nulos para eliminarlos. Realmente no se puede depender de esta característica ya que es muy automática a diferencia de C++.

Espero que ayude!

3

Sin embargo, mi entrevistador quería escuchar algo más.

espero que querían oír una respuesta como la que Marc Gravell ha publicado aquí, sino que se basa en un modelo excesivamente simplificado de cómo el recolector de basura de trabajo máquinas virtuales que no tiene ninguna semejanza con la realidad.

Por ejemplo, la llamada a GC.Collect podría optimizar la llamada final, en cuyo caso no hay raíces globales, por lo que se recopilan todos los bloques asignados en el montón. O el compilador puede crear una nueva entrada en el marco de la pila para cada temporal (no solo las variables en el código fuente) que mantiene todo accesible y no se recoge nada.O el compilador podría intercambiar el orden de la creación de las cadenas a y b y recoger el objeto Random se refiere la WeakReference antes de que el método se invoca Target causando una excepción null referencia para que el otro Random no es ni siquiera asignados.

+0

¿Qué quiere decir cambiar las cadenas, y cómo es relevante para la 'WeakReference'? –

+0

Me refiero a ejecutar 'nueva WeakReference (new Random()). Target.Next (0, 1) == 1? "Lo que sea 1": "Lo que sea 2" 'antes de ejecutar' new Random(). Next (0, 1) == 1? "Lo que sea 1": "Lo que sea 2" '. –

+0

Oh, me perdí la mitad de eso, la colección temprana del objetivo + excepción 'WeakReference' podría ocurrir en cualquier orden, es solo que solo afecta al otro' Random' si se reordenan. Y en este caso, el compilador es libre de reordenar porque 'nadie lo sabrá jamás'. –

Cuestiones relacionadas