2011-11-19 13 views
12

Questa è una domanda che mi è stata posta recentemente durante la mia intervista: Quali oggetti "casuali" sono stati raccolti durante la chiamata "GC.Collect()"?Quali di questi oggetti sono idonei per la garbage collection?

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(); 

ho risposto che questa è una domanda specifica dell'implementazione e dipende molto dalla GC attuazione ed i corrispondenti riferimenti semantici deboli. Per quanto ne so, le specifiche C# non forniscono una descrizione esatta di cosa dovrebbe fare GC.Collect e come devono essere gestiti i riferimenti deboli.

Tuttavia, il mio intervistatore voleva sentire qualcos'altro.

+3

Sei stato troppo educato. La mia risposta sarebbe se ci fosse qualcosa di terribilmente sbagliato ... –

+0

sarebbe bello se anche il tag 'Java' fosse aggiunto a questa domanda. – Bhushan

risposta

13

Sia Random() istanze e la WeakReference sono ammissibili per la raccolta:

  • Il primo Random non è stato immagazzinato in un locale, per non parlare di un locale che viene poi letta.
  • Il secondo Random è stato passato ad un WeakReference, quindi sarebbe OK per raccogliere comunque, ma il WeakReference non si tiene da nessuna parte, in modo che anche è idoneo per la raccolta.

Nessuna delle stringhe sono (ci sono solo 2 istanze di stringa qui, non 4, anche se è stato raggiunto ogni possibile percorso di codice): perché sono letterali nel codice C#, sono internati una volta che esistono.

+0

Sì, ovviamente, la domanda riguardava gli oggetti "Random", mi dispiace, che ho dimenticato di dirlo. –

+0

Ora, si può dire che la mia risposta è errata ed è la risposta giusta ** entrambi sono? ** –

+0

Sì; chiarito - vedi aggiornamento –

9

È vero che questo è dipendente dall'implementazione (e dal compilatore). Se tutto questo è nello stesso metodo, il tuo non può sapere quali oggetti sono ancora nello stack. Poiché gli oggetti in pila sono ancora referenziati, non sarebbero collezionabili.

Ciò che l'intervistatore ha voluto che sia più probabile fare è verificare quali oggetti sono ancora raggiungibili al richiamo di GC.Collect assumendo un'implementazione "perfetta" che scarta tutto quanto prima possibile.

+0

Perché il downvote? Questo è importante sapere quando si codificano i test delle unità che coinvolgono il comportamento del GC, sto parlando di esperienza qui. Ho fatto una differenza esplicita tra ciò che l'intervistatore probabilmente voleva sentire e ciò che è la realtà tecnica. – Zarat

+0

+1 Per essere la prima risposta corretta che ho letto. "assumendo una perfetta implementazione". Dato che la domanda non ha senso, mi asterrò dal fare ipotesi su ciò che l'intervistatore pensava di chiedere. –

1

GC.Collect è come in Java equivalente a System.gc()

It "consiglia" per verificare la presenza di valori nulli per eliminarli. Non si può davvero dipendere da questa caratteristica poiché è veramente automatica a differenza del C++.

Spero che aiuti!

3

Tuttavia, il mio intervistatore voleva sentire qualcos'altro.

mi aspetto che volevano sentire una risposta come quella che Marc Gravell ha postato qui, ma che si basa su un modello di come garbage collection macchine virtuali lavoro troppo semplificata, che non ha alcuna somiglianza con la realtà.

Ad esempio, la chiamata a GC.Collect potrebbe ottenere una coda ottimizzata, nel qual caso non ci sono radici globali in modo da raccogliere tutti i blocchi allocati nell'heap. O il compilatore potrebbe creare una nuova voce sullo stack frame per ogni temporaneo (non solo variabili nel codice sorgente) che mantiene tutto raggiungibile e non viene raccolto nulla.O il compilatore potrebbe invertire l'ordine della creazione delle corde a e b e raccogliere l'oggetto Random cui si riferisce l'WeakReference prima del metodo Target viene richiamato causando un'eccezione null riferimento così l'altro Random è mai assegnati.

+0

Cosa intendi per scambiare le stringhe e in che modo è pertinente al "Debolezza"? –

+0

Voglio dire eseguire 'new WeakReference (new Random()). Target.Next (0, 1) == 1? "Whatever 1": "Whatever 2" 'prima di eseguire' new Random(). Next (0, 1) == 1? "Whatever 1": "Whatever 2" '. –

+0

Oh, mi sono perso la metà di questo, la prima raccolta dell'obiettivo + dell'eccezione 'WeakReference' potrebbe avvenire in entrambi gli ordini, è solo che influenza solo gli altri' Random' se sono riordinati. E in questo caso il compilatore è libero di riordinare perché "nessuno lo saprà mai". –