2013-05-08 8 views
5

Was passiert, wenn ich ein Datenelement durch Verweis auf eine Funktion übergebe, und während diese Funktion ausgeführt wird, startet der Garbage Collector und verschiebt das Objekt mit dem Datenelement in den Speicher?Weitergabe von Datenelementen per Referenz

class SomeClass 
{ 
    int someDataMember; 

    void someMethod() 
    { 
     SomeClass.someFunction(ref someDataMember); 
    } 

    static void someFunction(ref int i) 
    { 
     i = 42; 

     int[] dummy = new int[1234567890]; 
     // suppose the Garbage Collector kicks in here 

     i = 97; 
    } 
} 

Wie stellt die CLR sicher, dass Referenzparameter während der Garbage Collection nicht ungültig werden? Sind sie genau wie Klassenreferenzen?

+1

mögliche Duplikate von [C# -Parameter durch Verweis und .net Garbage Collection] (http://StackOverflow.com/Questions/2500851/c-sharp-Parameters-by-Reference-and-Netz-Garbage-Collection) –

+0

Eric Lipperts Antwort auf die verbundene Frage von @rightfold beantwortet dies perfekt. –

+0

Sie werden angepasst, weil jeder Methodenparameter als Wurzel betrachtet wird und alle Wurzeln angepasst werden (es heißt im Buch "CLR via C#") –

Antwort

5

Nun, das Leben ist nicht einfach für den Müllsammler. Aber es weiß, wie man mit solchen inneren Zeigern umgeht. Gut versteckt aus verwalteten Sprachen wie C# und VB.NET, ist es in C++ sichtbar, wo innere Zeiger leicht durch die Sprachsyntax erzeugt werden können. Stan Lippman von C++ Primer Fame hat eine blog post über sie, was einige primäre Motivation für die interior_ptr Schlüsselwort in C++/CLI verfügbar.

Der Jitter geht einen Schritt darüber hinaus, er markiert die Referenz als GC_CALL_INTERIOR und gibt den spezifischen Fall eines Arguments an, das ein Innenzeiger sein kann. Mit dem Quellcode, der in der SSCLI20-Distribution verfügbar ist, können Sie sehen, wie der Inhalt des GC gehandhabt wird. Es ist nicht sehr kompliziert, ein Ausschnitt aus gcsmp.cpp, GCHeap :: Umzug() -Methode:

if (flags & GC_CALL_INTERIOR) 
    { 
     if ((o < gc_heap::gc_low) || (o >= gc_heap::gc_high)) 
     { 
      return; 
     } 
     o = gc_heap::find_object (o, gc_heap::gc_low); 

     offset = (BYTE*)object - o; 
    } 

So, kurz gesagt, eine sehr schnelle Prüfung zu entdecken, dass es nicht ein Zeiger sein kann, dass verweist auf ein Mitglied eines Referenztypobjekts, indem es den Zeiger gegen die unteren/oberen Grenzen des GC-Heapsegments prüft. Dann ein bisschen graben, um den inneren Zeiger auf das Objekt abzubilden, das das Mitglied enthält. Sehen Sie sich den SSCLI20-Quellcode an, um diesen Code zu sehen.

0

Der Garbage Collector führt eine Liste aller Zeiger auf ein Objekt. Objekte werden nur dann entsorgt, wenn auf dieses Objekt keine Zeiger mehr vorhanden sind.
In Ihrem Fall wird Ihre Funktion einen Zeiger auf das Objekt (mit dem Namen "i") haben und GC wird dieses Objekt niemals entsorgen.

Sie können einen vollständigen Artikel lesen, wie der GC funktioniert here.

+0

Ich spreche über das Bewegen von lebenden Objekten, nicht über die Entsorgung toter Objekte. (Auch "i" zeigt nicht auf ein Objekt, sondern auf ein Datenelement.) – fredoverflow

+0

Ok, Sie sprechen also nur über die Kompaktierungsphase von GC? – Fabske

Verwandte Themen