2015-10-16 20 views
6

Właśnie natknąłem się na dziwne "zachowanie" Garbage Collectora dotyczące System.Threading.ThreadLocal<T>, którego nie potrafię wyjaśnić. W normalnych okolicznościach instancje ThreadLocal<T> będą gromadzone podczas usuwania z zakresu, nawet jeśli nie zostaną prawidłowo rozmieszczone, z wyjątkiem sytuacji, gdy są częścią cyklicznego wykresu obiektów.Przeciek pamięci, gdy ThreadLocal <T> jest używany w cyklicznym wykresie

Poniższy przykład demonstruje problem:

public class Program 
{ 
    public class B { public A A; } 
    public class A { public ThreadLocal<B> LocalB; } 

    private static List<WeakReference> references = new List<WeakReference>(); 

    static void Main(string[] args) { 
     for (var i = 0; i < 1000; i++) 
      CreateGraph(); 

     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 

     // Expecting to print 0, but it prints 1000 
     Console.WriteLine(references.Count(c => c.IsAlive)); 
    } 

    static void CreateGraph() { 
     var a = new A { LocalB = new ThreadLocal<B>() }; 
     a.LocalB.Value = new B { A = a }; 
     references.Add(new WeakReference(a)); 

     // If either one of the following lines is uncommented, the cyclic 
     // graph is broken, and the programs output will become 0. 
     // a.LocalB = null; 
     // a.LocalB.Value = null; 
     // a.LocalB.Value.A = null; 
     // a.LocalB.Dispose(); 
    } 
} 

Chociaż nie nazywając Dispose nie jest dobra praktyka, ale jest to projekt CLR, aby oczyścić zasoby (poprzez wywołanie finalizatora) w końcu, nawet jeśli Dispose nie nazywa .

Dlaczego ThreadLocal zachowuje się inaczej pod tym względem i może powodować wycieki pamięci, jeśli nie zostaną prawidłowo usunięte w przypadku wykresu cyklicznego? Czy to według projektu? A jeśli tak, to gdzie jest to udokumentowane? Czy jest to błąd w GC CLR?

(Przetestowano pod .NET 4.5).

+0

[David Kean] (https://twitter.com/davkean) potwierdził, że jest to błąd. – Steven

+0

[Kliknij] (https://mobile.twitter.com/davkean/status/655067698511024128). – Steven

Odpowiedz

0

Microsoft's David Keanconfirmed, że to rzeczywiście jest błąd.

+0

Czy masz link do dokładnego tweeta/numeru? Twój oryginalny komentarz pochodził z października zeszłego roku, więc kontekst jest tu trochę zagubiony. –

+0

@JeffDammeyer Zaktualizowałem swoją odpowiedź za pomocą linku. – Steven

+0

Podczas gdy tweet może teoretycznie odpowiedzieć na pytanie, [byłoby lepiej] (// meta.stackoverflow.com/q/8259), uwzględnij tutaj istotne części tweeta. Dzieje się tak dlatego, że twitter może być zablokowany dla kilku użytkowników (w college'u/przemyśle). Zajrzyj do [tego meta postu] (http://meta.stackoverflow.com/a/313037/4099593) po więcej szczegółów. –

-3

Powodem jest to, że nie dzwonisz do dyspozycji. Śmieciarz będzie tylko sprzątał obiekty, które mają finalizatory w ostateczności.

+2

I zgadnij, co ... 'TheadLocal ' faktycznie * ma * finalizatora. – Steven