Ein kleines Demo Programm
Anbei ist ein kleines Demo-Programm, welches die Arbeitsweise der GC demonstriert. Es ist in zwei Units aufgeteilt.
Unit: uSampleObject.pas
In dieser
Unit wird ein Interface deklariert, welches nur eine einfache Zugriffsmethode hat, die uns die ID des zugehörigen Objektes zurückliefert.
Delphi-Quellcode:
type
IMyInterface = interface
function GetMyNumber: Integer;
end;
Auch ist das implementierende Objekt in der
Unit deklariert. Hier habe ich gleichzeitig noch ein kleines .NET Feature genutzt: Klassenkonstruktoren und Klassenvariablen. Dazu schreibe ich hier nicht viel weiter.
Hinweis:
Die Klassenmethode GetNextId (Achtung, nicht thread-safe) erhöht intern einen Klassenvariable (FIdCounter) und liefert den neuen Wert zurück. Damit kann jedes Objekt eine eindeutige ID zurückliefern. Dieses habe ich ausschließlich genutzt, damit im Debug-Log verfolgt werden kann, auf welches Objekt jeweils zugegriffen wird.
Hier die wichtigen Teile der Klassendefinition:
Delphi-Quellcode:
type
MyInterfacedObject = class(System.Object, IMyInterface)
strict private
FMyNumber: Integer;
procedure LogToDebugView(aLine: String);
strict protected
procedure Finalize; override;
public
constructor Create();
function GetMyNumber: Integer;
end;
Der Rest kann dem angehängtem Beispiel entnommen werden.
Das WinForm: uFormMain.pas
Ich habe das Form in drei Bereiche aufgeteilt. Abschnitt [1] zeigt den Zusammenhang zwischen Objekt-Referenzen und Interface-Referenzen. Abschnitt [2] ermöglicht das schnellere Füllen des Speichers, um das Verhalten der GC einfacher zu beurteilen. Abschnitt [3] dient dem Management der GC.
Alle Aktionen (Objekt erstellen und zerstören, Abfrage der Objekt-ID) werden im
Ereignisprotokoll in Delphi 2005 mitgeschrieben und angezeigt.
Test 1
Starte das Programm (neu). Erstelle ein Objekt. (1) Lasse Dir die Objekt-Nummer anzeigen (2). Weise es dem Interface zu (4).
Jetzt haben wir zwei Referenzen auf das gleiche Objekt. Lasse Dir die Interface-Nummer anzeigen (5).
Diese sollte jetzt gleich der im Objekt sein. Lösche das Interface. (6) Starte den GC. (11) Im Log sollte jetzt nicht erscheinen, dass Objekte freigeben werden, da das Objekt immer noch durch die Objektvariable (1) angesprochen werden kann. In Delphi für
Win32 wäre die jetzt ungültig

Jetzt gib das Objekt frei (3). Weiterhin taucht im Debugger-Log sehr wahrscheinlich keine Message über die Freigabe auf. Wenn Du jetzt einen Tag wartest, wird diese wahrscheinlich irgendwann man auftauchen. Nun zwingen wir nochmal die GC aufzuräumen (11) Jetzt erscheint auch die Meldung, dass das Objekt freigegeben wurde.
Test 2
Starte das Programm (neu). Erstelle einmal 10 Objekte. (7) Beachte, dass keines dieser Objekte jetzt mehr referenziert wird. Allerdings befinden sich alle Objekte weiterhin im Speicher, der GC hat diese sehr wahrscheinlich noch nicht freigegeben. Jetzt wieder auf (11) und alle Objekte werden freigegeben.
Test 3
Starte das Programm (neu). Erstelle mehrmals mehrere Objekte (7). Nach einer Weile wirst Du im Debug-Log bemerken, dass die GC anspringt und die Objekte selbständig freigibt. Das System hat automatisch den Bedarf an Speicher bemerkt und angefangen einige Objekte aufzuräumen.
Das ist das beste einfache Beispiel, um zu sehen dass und wie die GC arbeitet.