2010-07-08 18 views
6

Tengo una pregunta muy básica.Recolección de basura del objeto creado en el bucle infinito

Me escribe un bucle como este:

while(true) 
{ 
    MyTestClass myObject = new MyTestClass(); 
} 
  1. Cuando será el objeto creado en el bucle, el recolector de basura?
  2. Además, para cada iteración, ¿es que la nueva ubicación de memoria es asignada a la referencia myObject?
  3. ¿Qué pasa si escribo myObject = null; al final de cada iteración?

Respuesta

9
  1. siempre que a GC le guste, francamente; la variable nunca se lee, por lo que siempre es elegible
  2. myObject es la variable - que tiene una posición fija en la pila para la referencia; sin embargo, cada new MyTestClass() es un objeto diferente , creado en algún lugar del espacio de montón disponible; diferente cada vez
  3. sin diferencia alguna; estrictamente hablando, hay algunas complejidades que implican el punto de declaración real de la variable (en IL) y cómo se implementa realmente while, pero eso solo se muestra después de salir del ciclo. Y puesto que en cada iteración se puede asignar inmediatamente, no hay una diferencia tangible aquí
+0

¿Seguro que la variable tiene necesariamente un lugar fijo cada pasarela? Dado que la declaración de variable está dentro del ciclo, ¿no es este un escenario más dinámico en el que sería capaz de capturar diferentes "instancias" de myObject si las empleó construyendo una expresión Lambda dentro del ciclo que tuvo una vida más allá del ciclo? ¿O es eso un truco de compilación? – Tormod

+0

¿Es correcto que la variable myObject tenga una posición fija en la pila? Creo que cada vez que una nueva variable llamada 'myObject' se crea en la pila (y una creada en la iteración anterior es obviamente eliminada). ¿Estoy en lo correcto? – Amey

+1

@Tormod, en ese caso, el almacenamiento de un campo en el cierre para la lambda se crearía dinámicamente, y el campo se poblaría copiando el valor contenido en la variable, pero eso no afecta la ubicación de la variable en la pila. –

5

Cuando se creó el objeto en el bucle, recoge la basura?

En algún momento después de eliminar la última referencia al mismo. Se crea y elimina una nueva referencia en cada iteración de bucle, por lo que el GC puede recoger estos objetos cuando lo desee. En la práctica, es probable que esto suceda cuando su programa llena por completo la generación cero.

Además, para cada iteración, ¿es que la nueva ubicación de memoria está asignada a la referencia myObject?

Sí.

¿Qué pasa si escribo myObject = null; al final de cada iteración?

No hará ninguna diferencia. La configuración myObject = null; quita esa referencia al objeto, pero la referencia se elimina de todos modos cuando la variable myObject se reasigna en la siguiente iteración de bucle.

+3

es el último punto; en el nivel IL (que es lo que le importa a GC), los ámbitos no existen y 'myObject' se declara en el preámbulo IL (suponiendo que no se capture), por lo que existe (como un" local "con un valor) para toda la duración del método. No se borra explícitamente al salir del alcance (C#). Simplemente: nunca se lee más allá de este punto. –

+0

Olvidé que la variable IL no observa el bloque C# ... –

3

Vamos a aclarar algunas cosas. Cada vez que toque el interior del ciclo, myObject se asignará a una nueva dirección. Entonces, todo lo que este lazo hace es asignar nuevas direcciones de memoria para un solo nombre de variable. Por lo tanto:

  1. El GC recogerá todas las asignaciones anteriores, probablemente casi inmediatamente ya que la variable nunca se usa.
  2. Sí.
  3. No importa. La variable aún no se usa.
0

Como una adición a todas las demás respuestas:

usted podría hacer su clase de una estructura. Luego estará en la pila y se descartará para cada iteración. Si tu estructura hace nuevas clases, entonces estás de regreso al punto uno. Y si su estructura es grande, podría afectar negativamente al rendimiento, pero si no es pequeña, podría afectar positivamente el rendimiento.

+0

Eso no es correcto. Si fuera una estructura, no se descartaría para cada iteración, sería la misma instancia para cada iteración y no se descartaría hasta que el método salga. Sin embargo, obtendría un nuevo valor para cada iteración. – Guffa

+0

¿Esto significa, en el caso de struct, que se usará la misma variable pero tendrá diferentes valores para sus atributos en cada iteración? es decir, la variable struct declarada dentro del ciclo NO se eliminará de la pila al final de cada iteración. ¿Tengo razón? – Amey

+0

Si las variables de bucle se reventan o no se debe al compilador, pero el * comportamiento * de dichas variables es que se restablecen (completamente nuevas) en cada iteración. Si desea que un valor variable sobreviva en iteraciones, debe declararlo fuera del ciclo. –

4

Vamos a añadir un código que utiliza realmente el objeto de hacerlo más claro lo que realmente sucede:

while(true) { 
    // Here a new instance is created in each iteration: 
    MyTestClass myObject = new MyTestClass(); 
    // Here the instance is still in use 
    // until here: 
    myObject.CallSomething(); 
    // Here the instance isn't used any more, 
    // so the GC can collect it if it wants to. 
    // Setting the reference to null here: 
    myObject = null; 
    // is useless, as the GC already knows that the 
    // instance is unused before that time. 
} 
+0

+1 Refiérase a nulo, de hecho, el tiempo de ejecución hará que estos sean elegibles para GC tan pronto como ya no se usen, es decir, incluso en métodos grandes donde declare muchas variables de objeto, anulándolas parcialmente en el método, aunque legible - no incurre en ninguna diferencia en el comportamiento. –

+0

@ Adam: Si este es el caso, ¿cuándo deberíamos asignar un objeto al valor nulo? Cuando sabemos que la variable no se utilizará después de cierta línea de código (por ejemplo, después de myObject.CallSomething()), ¿está bien si no se establece en nulo? – Amey

+0

@Amey Sí, lo siento, no estaba muy claro; establecerlo como nulo no es ** obligatorio **, el tiempo de ejecución tiene la inteligencia para resolverlo. –