2011-12-01 10 views
7

Czytam o CUI zbieracza i jak CLR buduje wykresy obiektów. Odniesienia Rozdział różne korzenie, które mogą być aktywne dla obiektu:C# Garbage Collection Active Root

• Odniesienia do globalnych obiektów (choć te są niedozwolone w C#, CIL kod robi alokacji pozwoleń globalnych obiektów)
• Odniesienia do dowolnego statyczne obiekty/statycznych pól
• Odniesienia do lokalnych obiektów w bazie kodu źródłowego aplikacji
• Odsyłacze do sprzeciwu parametry przekazane do metody
• odwołań do obiektów czeka na fina lized (opisany w dalszej części tego rozdziału)
• Dowolny rejestrze procesora, która odwołuje obiekt

Zastanawiałem się, czy ktoś może podać przykłady tych korzeni w kodzie?

Dzięki

Odpowiedz

7

Załóżmy, uruchom następujący program:

class Program 
{ 
    static Class1 foo = new Class1(); 

    static void Main(string[] args) 
    { 
     Class2 bar = new Class2(); 

     Class3 baz = new Class3(); 
     baz = null; 

     Debugger.Break(); 

     bar.Run(); 
    } 
} 

Gdy program łamie do debuggera, istnieją 3+ obiekty, które nie kwalifikują się do zbierania śmieci, ponieważ z następujących dokumentów:

  • Class1 obiekt odwołuje polu statycznym foo
  • string[] obiekt odwołuje parametru args
  • zero lub więcej string obiektów odwołuje obiektu string[] odwołuje args
  • z Class2 obiektu wskazywanego przez zmienną lokalną bar

Przedmiotem Class3 kwalifikuje się do śmieci i mogą już zostać zebrane lub czekać na sfinalizowanie.

Odniesienia do obiektów globalnych nie są dozwolone w języku C#. Referencje w rejestrach procesorów są szczegółami implementacji maszyny wirtualnej.

+3

W tym momencie 'bar' może faktycznie być kolekcjonowany w trybie zwolnienia, ponieważ nie jest on przywoływany po przerwie. –

+0

Brian ma rację, 'bar' będzie utrzymywany przy życiu tylko w * trybie debugowania * na pewno do końca metody Main, która służy wyłącznie do debugowania wygody - w trybie wydania' bar' może zostać zebrany. – BrokenGlass

+0

Wierzę, że jeśli używasz DEBUG, obiekty są zawsze bezpieczne, dopóki funkcja się nie zakończy. Uważam jednak, że masz zoptymalizowany kod. –

1
class Test 
    { 
     static object ImARoot = new object(); //static objects/static fields 

     void foo(object paramRoot) // parameters I'm a root to but only when in foo 
     { 
      object ImARoot2 = new object(); //local objects but only when I'm in foo. 

      //I'm a root after foo ends but only because GC.SuppressFinalize is not called called (typically in Dispose) 
      SomethingWithAFinalizer finalizedRoot = new SomethingWithAFinalizer(); 


     } 
    } 

Jeśli kiedykolwiek chcesz dowiedzieć się, jakie obiekt jest zakorzenione w danym momencie można używać SOS (w Visual Studio 2005 lub później lub w WinDbg) i użyj polecenia gcroot!.

Powiązane problemy