2010-01-27 26 views
19

Estoy un poco confundido acerca del hecho de que en C# solo los tipos de referencia obtienen basura recolectada. Eso significa que GC selecciona solo los tipos de referencia para la desasignación de memoria. Entonces, ¿qué ocurre con los tipos de valores ya que también ocupan memoria en la pila?Destruyendo un objeto struct en C#?

Respuesta

29

Para empezar, si están en la pila o en una parte del montón depende del contexto del que forman parte; si están dentro de un tipo de referencia, estarán en el montón de todos modos. (Debería considerar cuánto le importa realmente la división pila/montón de todos modos, como escribió Eric Lippert, es largely an implementation detail).

Sin embargo, básicamente la memoria de tipo de valor se recupera cuando se recupera el contexto, por lo que cuando la pila está Apareció regresando de un método que "reclama" todo el marco de la pila. Del mismo modo, si el valor del tipo de valor es realmente parte de un objeto, entonces la memoria se recupera cuando ese objeto es basura.

La respuesta corta es que usted no tiene que preocuparse por ello :) (Esto supone que no tiene nada otra que la memoria que preocuparse, por supuesto - si tiene estructuras con referencias a los mangos nativas que necesitan de liberación, que es un escenario un tanto diferente.)

+0

Gracias por la referencia de este completo artículo. Encontré la directiva global de Eric Lippert muy consistente con toda la filosofía de C#: "Tenga solo una preocupación sobre la semántica, nosotros nos ocupamos del resto para usted" –

3

Un tipo de valor en la pila se elimina de la pila cuando se sale del alcance.

3

Los tipos de valor se destruyen tan pronto como salen del alcance.

0

tipos de valor conseguirían desasignado cuando se retira el marco de pila después de que se haya ejecutado i asumiría

0

también me gustaría añadir que la pila está en un nivel de subproceso, y el montón está en el nivel de dominio de la aplicación.

Por lo tanto, cuando termina un hilo, reclamó la memoria de pila utilizada por ese hilo específico.

7

Hay demasiados verbos en esta pregunta, como destruido, reclamado, desasignado, eliminado. Eso no se corresponde bien con lo que realmente sucede. Una variable local simplemente deja de ser, Norwegian parrot style.

Un método tiene un solo punto de entrada, lo primero que sucede es que se ajusta el puntero de la pila de la CPU. Creando un "marco de pila", espacio de almacenamiento para las variables locales. El CLR garantiza que este espacio se inicializa en 0, de lo contrario no es una característica que use con fuerza en C# debido a la regla de asignación definida.

Un método tiene un único punto de salida, incluso si su código de método está salpicado de múltiples instrucciones return. En ese punto, el puntero de la pila simplemente se restaura a su valor original. En efecto, "olvida" que las variables locales estuvieron allí. Sus valores no están "borrados" de ninguna manera, los bytes todavía están allí. Pero no durarán mucho, la próxima llamada en su programa los sobrescribirá nuevamente. La regla de inicialización cero de CLR garantiza que nunca podrá observar esos valores antiguos, que serían inseguros.

Muy, muy rápido, no requiere más que un ciclo de procesador único. Un efecto secundario visible de este comportamiento en el lenguaje C# es que los tipos de valores no pueden tener un finalizador. Asegurándose de que no se necesita hacer trabajo adicional.

+0

¡Esta variable local ya no existe! ¡Ha dejado de ser! Es una ex-variable. :) –

17

Estoy un poco confundido acerca del hecho de que en C# solo los tipos de referencia obtienen basura recolectada.

Esto no es un hecho.O, más bien, la verdad o falsedad de esta afirmación depende de lo que quiere decir con "obtener basura recolectada". El recolector de basura sin duda mira los tipos de valor al recolectar; esos tipos de valores podrían ser vivo y se aferra a un tipo de referencia:

struct S { public string str; } 
... 
S s = default(S); // local variable of value type 
s.str = M(); 

cuando el recolector de basura se ejecuta sin duda se ve en s, ya que tiene que determinar que s.str sigue vivo.

Mi sugerencia: aclarar precisamente lo que quiere decir con el verbo "obtiene basura recolectada".

GC selecciona solo los tipos de referencia para la desasignación de memoria.

De nuevo, esto no es un hecho. Suponga que tiene una instancia de

class C { int x; } 

la memoria para el número entero será en el montón de basura recogida, y por lo tanto reclamado por el recolector de basura cuando la instancia de C se convierte en unrooted.

¿Por qué cree en la falsedad de que solo la memoria de los tipos de referencia es desasignada por el recolector de basura? La afirmación correcta es que la memoria que fue asignada por el recolector de basura es desasignada por el recolector de basura, lo que creo que tiene perfecto sentido. El GC lo asignó por lo que es responsable de limpiarlo.

Entonces, ¿qué ocurre con los tipos de valores ya que también ocupan memoria en la pila?

Nada les sucede a ellos. Nada tiene que sucederles. La pila es un millón de bytes. El tamaño de la pila se determina cuando se inicia el hilo; comienza en un millón de bytes y permanece un millón de bytes durante toda la ejecución del hilo. La memoria en la pila no se crea ni se destruye; solo sus contenidos son cambiados.

+26

"La memoria en la pila no se crea ni se destruye" - Propongo que llamemos a esto ** Ley de Preservación de Memoria de [Stack] de Lippert **. :) –

0

Cada instancia de tipo de valor en .NET formará parte de otra cosa, que podría ser una instancia de tipo de valor adjunta más grande, un objeto de montón o un marco de pila. Cada vez que surja cualquiera de esas cosas, cualquier estructura dentro de ellas también se hará realidad; esas estructuras continuarán existiendo siempre que la cosa que las contiene lo haga. Cuando lo que contiene la estructura deja de existir, la estructura también lo hará. No hay forma de destruir una estructura sin destruir el contenedor, y no hay forma de destruir algo que contiene una o más estructuras sin destruir las estructuras que contiene.