2010-01-27 19 views
19

Sono un po 'confuso riguardo al fatto che in C# solo i tipi di riferimento ottengono la garbage collection. Ciò significa che GC seleziona solo i tipi di riferimento per la de-allocazione della memoria. Quindi cosa succede con i tipi di valore in quanto occupano anche memoria in pila?Distruggere un oggetto struct in C#?

risposta

29

Per cominciare, se sono nello stack o parte dell'heap dipende dal contesto in cui fanno parte - se sono all'interno di un tipo di riferimento, saranno comunque nell'heap. (Dovresti considerare quanto ti importa davvero dello stack/heap si divide comunque - come ha scritto Eric Lippert, è largely an implementation detail.)

Tuttavia, in fondo la memoria di tipo valore viene recuperata quando il contesto viene recuperato - quindi quando lo stack è saltato fuori da un metodo, che "recupera" l'intero frame dello stack. Allo stesso modo se il valore del tipo valore è in realtà parte di un oggetto, quindi la memoria viene recuperata quando tale oggetto viene sottoposto a garbage collection.

La risposta breve è che non devi preoccuparti :) (Questo presuppone che tu non abbia nulla altro della memoria di cui preoccuparti, ovviamente se hai strutture con riferimenti alle maniglie nativi che hanno bisogno di rilascio, questo è uno scenario un po 'diverso.)

+0

Grazie per il riferimento a questo articolo completo. Ho trovato la direttiva globale di Eric Lippert molto coerente con l'intera filosofia C#: "Solo una preoccupazione per il semantico, penseremo noi al resto" –

3

Un tipo di valore sullo stack viene rimosso dallo stack quando esce dall'ambito.

3

I tipi di valore vengono distrutti non appena escono dal campo di applicazione.

0

tipi di valore otterrebbero deallocato quando lo stack frame viene rimosso dopo che è stato eseguito vorrei assumere

0

Vorrebbe anche aggiungere che stack è a un livello di thread e heap è a livello di dominio dell'applicazione.

Quindi, quando un thread termina, recupera la memoria dello stack utilizzata da quel thread specifico.

7

Ci sono troppi verbi usati in questa domanda, come distrutti, recuperati, deallocati, rimossi. Ciò non corrisponde bene a ciò che accade realmente. Una variabile locale semplicemente cessa di essere, Norwegian parrot style.

Un metodo ha un singolo punto di ingresso, la prima cosa che accade è che il puntatore dello stack della CPU viene regolato. Creazione di uno "stack frame", spazio di archiviazione per le variabili locali. Il CLR garantisce che questo spazio sia inizializzato a 0, non altrimenti una caratteristica che usi fortemente in C# a causa della regola di assegnazione definita.

Un metodo ha un unico punto di uscita, anche se il codice del metodo è costellato di più istruzioni return. A quel punto, il puntatore dello stack viene semplicemente riportato al suo valore originale. In effetti "dimentica" che le variabili locali sono sempre lì. I loro valori non sono "scrostati" in alcun modo, i byte sono ancora lì. Ma non dureranno a lungo, la prossima chiamata del tuo programma li sovrascriverà di nuovo. La regola di inizializzazione zero CLR assicura che non puoi mai osservare quei vecchi valori, che sarebbero insicuri.

Molto, molto veloce, non richiede più di un singolo ciclo del processore. Un visibile effetto collaterale di questo comportamento nel linguaggio C# è che i tipi di valore non possono avere un finalizzatore. Garantire che non ci sia lavoro extra da fare.

+0

Questa variabile locale non esiste più! Ha smesso di essere! È un'ex variabile. :) –

17

Sono un po 'confuso sul fatto che in C# solo i tipi di riferimento ottengono la garbage collection.

Questo non è un dato di fatto.O, piuttosto, la verità o la falsità di questa affermazione dipende da cosa intendi per "raccogliere i rifiuti". Il garbage collector guarda certamente ai tipi di valore durante la raccolta; questi tipi di valore potrebbe essere vivo e aggrappandosi a un tipo di riferimento:

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

quando il garbage collector corre certamente guarda s, perché ha bisogno di determinare che S.Str è ancora vivo.

Il mio suggerimento: chiarire esattamente cosa si intende per il verbo "ottiene garbage collection".

GC preleva solo i tipi di riferimento per la de-allocazione della memoria.

Ancora, questo non è un dato di fatto. Supponiamo di avere un'istanza di

class C { int x; } 

la memoria per l'intero sarà sul mucchio garbage collection, e quindi recuperati dal garbage collector quando l'istanza di C diventa senza radice.

Perché credi alla falsità che solo il ricordo dei tipi di riferimento è disaggregato dal garbage collector? L'affermazione corretta è che la memoria che era assegnata a dal garbage collector è deallocata dal garbage collector, che a mio avviso ha perfettamente senso. Il GC lo ha assegnato quindi è responsabile della sua pulizia.

Così che cosa accade con i tipi di valore in quanto occupano anche la memoria sullo stack?

Non succede loro niente. Niente deve accadere a loro. Lo stack è un milione di byte. La dimensione della pila viene determinata all'avvio del thread; inizia con un milione di byte e rimane un milione di byte durante l'intera esecuzione del thread. La memoria in pila non viene né creata né distrutta; solo il suo contenuto è cambiato.

+26

"La memoria nello stack non viene né creata né distrutta" - Propongo di chiamarla ** Legge di Lippert di [Stack] Memory Preservation **. :) –

0

Ogni istanza del tipo di valore in .NET sarà parte di qualcos'altro, che potrebbe essere un'istanza di tipo valore racchiuso più grande, un oggetto heap o una cornice stack. Ogni volta che una qualsiasi di queste cose viene alla luce, nascono anche tutte le strutture all'interno di esse; quelle strutture continueranno quindi ad esistere fintanto che la cosa che le contiene. Quando la cosa che contiene la struttura cessa di esistere, anche la struttura lo sarà. Non c'è modo di distruggere una struttura senza distruggere il contenitore, e non c'è modo di distruggere qualcosa che contiene una o più strutture senza distruggere le strutture in esse contenute.