Warum versucht der c # -Abfallsammler nicht, Speicher freizugeben, bis eine Anforderung erfüllt werden kann?

9

Betrachten Sie den folgenden Code:

%Vor%

Ich habe eine Klasse, BigObject, die ein 700MB-Array in ihrem Konstruktor erstellt und eine Finalize-Methode hat, die nichts anderes tut, als in die Konsole zu drucken. In Main erstelle ich zwei dieser Objekte, eins frei, und dann ein drittes.

Wenn dies für 32 Bit kompiliert wird (um den Speicher auf 2 Gigs zu beschränken), wird beim Erstellen des dritten BigObject eine Out-of-Memory-Ausnahme ausgelöst. Wenn der Speicher zum dritten Mal angefordert wird, kann die Anforderung nicht erfüllt werden und der Garbage Collector wird ausgeführt. Das erste BigObject, das zur Erfassung bereitsteht, verfügt jedoch über eine Finalisierermethode, die nicht gesammelt, sondern in der Finalisierungswarteschlange platziert wird. Der Müllsammler wird dann angehalten und die Ausnahme wird ausgelöst. Wenn der Aufruf von GC.Collect jedoch unkommentiert ist oder wenn die Finalize-Methode entfernt wird, wird der Code ordnungsgemäß ausgeführt.

Meine Frage ist, warum versucht der Garbage Collector nicht alles, um die Anforderung nach Speicher zu erfüllen? Wenn es zweimal ausgeführt wird (einmal zu finalisieren und wieder zu befreien), würde der obige Code gut funktionieren. Sollte der Garbage Collector nicht weiter abschließen und sammeln, bis kein Speicher mehr freigegeben werden kann, bevor die Ausnahme ausgelöst wird, und gibt es eine Möglichkeit, das Verhalten so zu konfigurieren (entweder im Code oder über Visual Studio)? >     

Sean Reid 06.02.2013, 07:56
quelle

2 Antworten

2

Es ist unbestimmbar, wenn der GC funktioniert und versucht, die Erinnerung wiederherzustellen.

Wenn Sie diese Zeile nach big1 = null hinzufügen. Allerdings sollten Sie vorsichtig sein, um GC zum Sammeln zu zwingen. Es ist nicht empfehlenswert, es sei denn, Sie wissen, was Sie tun.

%Vor%

Best Practice zum Erzwingen von Garbage Collection in C #

Wann sollte ich GC.SuppressFinalize () verwenden?

Garbage Collection in .NET (Generationen)

    
adt 06.02.2013 08:22
quelle
0

Ich schätze, weil die Zeit, die der Finalizer während der Garbage Collection ausführt, nicht definiert ist. Es wird nicht garantiert, dass Ressourcen zu einem bestimmten Zeitpunkt freigegeben werden (es sei denn, eine Close- oder Dispose-Methode wird aufgerufen.) Auch die Reihenfolge, in der die Finalizer ausgeführt werden, ist zufällig, sodass ein Finalizer auf ein anderes Objekt warten kann, während das Objekt darauf wartet .

    
sa_ddam213 06.02.2013 08:15
quelle