Anzeige

[C#] Dispose und Garbage Collection


Saber

Erfahrenes Mitglied
#1
Hallo zusammen!

Ich hab da mal eine grundlegende C#.NET-Frage. So wie ich das verstanden habe erledigt doch die Garbage Collection von .NET die komplette Speicherverwaltung, oder? Sie gibt also auch den nicht mehr benötigten Speicher wieder frei.

Nun, wieso wird dann überall geschrieben, dass man Dispose() zum Freigeben des Speichers verwenden sollte. Okay, bei größeren Resourcen seh ich´s ja ein. Die sollten so schnell wie möglich wieder freigegeben werden, wenn sie nicht mehr benötigt werden. Aber ansonsten?

Wer kann mir also einen kleinen Crash-Kurs in Sachen C#.NET´s Speicherverwaltung geben? :)

DANKE im Vorraus!!!

MfG
Mike
 
V

Vaethischist

#2
Ich kann zwar nicht für C# sprechen, aber in C++ ist die Garbage-Collection nur für lokal erzeugte Objekte, aber nicht für Objekte auf dem Heap zuständig. Dort werden mittels new erzeugte Objekte gespeichert (also im Prinzip alles was irgendwie mit Zeigern zu tun hat, kommt auf den Heap). Diese werden nicht automatisch entfernt.

Bsp:

Code:
...
{
CFile file;
CFile* fileptr = new CFile();

...
}
file wird bei Verlassen des Blocks entfernt, fileptr auch, aber der allozierte Speicher (für das CFile-Objekt) nicht. Beim Debug-Run kommt dann am Ende etwas mit "Detected Memory Leaks...", was einen darauf hinweist, das irgendwo ein alloziertes Objekt auf dem Heap rumschwirrt, das da nix zu suchen hat.
 

Saber

Erfahrenes Mitglied
#3
Danke für Deinen Beitrag ... aber zwischen C++ und C# liegen Welten, so glaube ich nicht, dass man die Speicherverwaltung beider Sprachen vergleichen kann.

Trotzdem danke. :)
 
V

Vaethischist

#4
Das mit den Welten glaube ich kaum... Die Garbage-Collection von Heap-Objekten ist weder trivial noch macht sie Sinn, wenn man weiß was man tut. ;)
 

Saber

Erfahrenes Mitglied
#5
Du bist nicht zufällig mein C++ Lehrer aus der Schule, oder? *fg*
Ironischerweise war das auch der Kursleiter von C#. ;)

Aber ich habs mittlerweile schon rausbekommen:
Die Garbage Collection von .NET regelt komplett alles. Man benötigt Dispose() nur dann, wenn man explizit wünscht, dass ein Objekt zu einem bestimmten Zeitpunkt zerstört wird und dessen Speicher freigegeben werden soll. Ansonsten regelt das die Garbage Collection, wenn die CPU genügend Freiraum hat, um die Arbeiten zu erledigen. :)
 

Asterix-Ac

Erfahrenes Mitglied
#6
Der Garbage Collector

Hi,

Der Garbage Collector ist die Müllverbrennungsanlage von .NET.

Normaler Weise hast Du keinen Einfluss darauf, wann der GC läuft. Das entscheidet das System. Du kannst ihn aber auch selber aktivieren. Damit solltest Du aber sparsam umgehen. -> Systemleisung sinkt rapiede.
Du kannst ihn benutzen, wenn Du ein Objekt mit <objekt> = null; zerstörst.
Wenn Du mehrere Objekte zerstörst, lass den GC erst am Ende laufen.

Der Aufruf : GC.Collect();
Wird von System geerbt, da in der System.Object deklariert und statisch.

Asterix
 
#8
Hallo,

Zu bestimmten Zeiten werden alle Objekte einer .NET-basierten Anwendung vom Garbage Collector durchlaufen, um diejenigen zu suchen, die nicht mehr referenziert werden. Letztere werden erst nach dem Auffinden tatsächlich endgültig verworfen. Der GC hat aber eine ihn kennzeichnende, spezifische Eigen-schaft: Es kann nicht vorhergesagt werden, wann er seine Arbeit aufnimmt. Ein freigegebenes Objekt wird also solange sein Dasein im Speicher fristen, bis der Garbage Collector es entdeckt – trotzdem ist es für den Programmcode unerreichbar.
Damit stellt sich sofort die Frage, nach welchen Kriterien der GC seine Arbeit aufnimmt. Als selbstständi-ge Ausführungseinheit (Thread) genießt er keine hohe Priorität und kann erst dann den Prozessor in An-spruch nehmen, wenn die Anwendung selbst beschäftigungslos ist. Theoretisch könnte das bedeuten, dass eine gestresste Anwendung dem Garbage Collector keine Chance lässt, überhaupt jemals in Aktion zu treten. Dem ist tatsächlich so, es gibt aber eine entscheidende Einschränkung: Noch bevor den Speicherres-sourcen der Anwendung die „Luft ausgeht“, ist die zweite Bedingung erfüllt, um die Speicherbereinigung mit dem Garbage Collector anzustoßen.
Der Garbage Collector wird spätestens dann nach allen nicht referenzierten Objekten suchen und ihren Speicherplatz freigeben, wenn die Speicherressourcen knapp werden.
Der Anstoß zum Einsammeln aller aufgegebenen Objekte kann im Programmcode mit

System.GC.Collect();

angestoßen werden. Die Suche nach allen freigegebenen Objekten nimmt natürlich Zeit in Anspruch und führt zu Performanceverlusten der laufenden Anwendung. Daher ist es nicht empfehlenswert, ohne ein gewichtiges Argument grundsätzlich bei jeder Objektzerstörung „zur Sicherheit“ zusätzlich immer den Aufräumprozess zu aktivieren.
 
#9
Original geschrieben von Vaethischist
Ich kann zwar nicht für C# sprechen, aber in C++ ist die Garbage-Collection nur für lokal erzeugte Objekte, aber nicht für Objekte auf dem Heap zuständig. Dort werden mittels new erzeugte Objekte gespeichert (also im Prinzip alles was irgendwie mit Zeigern zu tun hat, kommt auf den Heap). Diese werden nicht automatisch entfernt.

Bsp:

Code:
...
{
CFile file;
CFile* fileptr = new CFile();

...
}


file wird bei Verlassen des Blocks entfernt, fileptr auch, aber der allozierte Speicher (für das CFile-Objekt) nicht. Beim Debug-Run kommt dann am Ende etwas mit "Detected Memory Leaks...", was einen darauf hinweist, das irgendwo ein alloziertes Objekt auf dem Heap rumschwirrt, das da nix zu suchen hat.
Das was du meinst hat mit Garbage Collection nichts zu tun, es gibt im ANSI/ISO c++ auch keine Garbage Collector, nur in C++.NET (managed C++).

Wenn du den Speicher unbeding wieder freigeben willst solltest du deiner Klasse eine Dispose() Methode hinzufügen und von Hand aufrufen. Diese Methode sollte dann alle Ressource wieder freigen (Verbindungen schließen oder Referenzen auf NULL setzen) Damit umgehst du den GC Performanceeinbruch. Die Klasse selber wird dann irgendwann vom Garbage Collector zerstört, dies passiert spätestens dann wenn du den Speicher wieder benötigst.
 
#10
Ich habe da leider so meine Zweifel, ob es wirklich passiert, wenn Speicher benötigt wird. Ich bekomme bei einer grossen Optimierung immer wieder Abbrüche weil der Speicher voll ist. Recht enttäuschend aber sieht leider so aus.
 

Argbeil

Grünschnabel
#11
Was meinst du mit "bei einer großen Optimierung" ? Wenn bei einer Anwendung von dir der Speicher überläuft liegt das mit Sicherheit nicht am GarbageCollector.
 
#12
Was meinst du mit "bei einer großen Optimierung" ? Wenn bei einer Anwendung von dir der Speicher überläuft liegt das mit Sicherheit nicht am GarbageCollector.
Schön wäre es. Es sieht so aus als ob die GC durch die Optimierung einfach nicht die Zeit bekommt zu laufen. Die Anwendung ist nur zum Teil von mir, aber der Softwarelieferant schwört, dass sein Programm die Resourcen freigegeben hat. Nur die GC hat sie halt noch nicht gefunden. Sehr ärgerlich
 
#13
Wir wissen immer noch nicht, was mit "großer Optimierung" gemeint ist!

Wenn der GC freigegebene Ressourcen nicht wegräumt, sind doch irgendwo noch Referenzen darauf vorhanden oder sie sind nicht verwaltet.
 
Anzeige
Anzeige