Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Wie gibt TComponentList Objekte frei?


LCS - Mo 02.12.02 13:01
Titel: Wie gibt TComponentList Objekte frei?
Hallo Leute
ich verwende eine TComponentList um DB-Verbindungen in einem Programm zu verwalten. Das Prog besteht zur Zeit aus deinem Datenmodul und einem Hauptformular.
Das DM wird zuerst erzeugt. Im OnCreate erstelle ich die ComponentList.
Im Hauptfenster werden jetzt (testhalber) zwei Komponenten in die Liste eingefügt:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  i  := DM.lstCon.Add(TLCSConnection.Create(self, 'PIMS Datenbank'));
   if  i >= 0 then
     with DM.lstCon.Items[i] as TLCSConnection do begin
         if  Open then
             ShowMessage('Datenbank ' + IntToStr(i) + ' geöffnet');
       end;

  i  := DM.lstCon.Add(TLCSConnection.Create(self, 'GSHOP'));
   if  i >= 0 then
     with DM.lstCon.Items[i] as TLCSConnection do begin
         if  Open then
             ShowMessage('Datenbank ' + IntToStr(i) + ' geöffnet');
       end;

Das funktioniert auch alles wunderbar, die Anzahl der Einträge in lstCon (TComponentList) ist 2.

Dann gibt es einen Menüeintrag um das Programm zu beenden und da steht folgendes:

Quelltext
1:
2:
3:
4:
5:
  if  DM.lstCon.Count > 0 then
      for i := DM.lstCon.Count - 1 downto 0 do
         if  DM.lstCon.Items[i] <> nil then
            with DM.lstCon.Items[i] as TLCSConnection do
             Free;

Auch das funzt einwandfrei, der Destructor meiner Verbindungskomponenten wird durchlaufen.
Verschiebe ich jetzt allerdings diesen Codeblock in das OnDestroy des Datenmoduls, passiert gar nix mehr. Die Anzahl der Komponenten in der Liste ist 0. Das Leuchtet mir ja sogar noch ein, da der Owner der Verbindungskomps ja das Hauptfenster war, das an dieser Stelle bereits geschlossen wurde. Die Verbindungskomponenten werden also anscheinend mit dem Hauptformular gelöscht. Und jetzt kommt die eigentliche Frage: Warum wird dabei aber mein Destructor nicht ausgeführt? Und was soll die Eigenschaft OwnObjects der Componentliste bewirken, wenn die Objekte anscheinend doch zum Formular gehören?

Gruss Lothar


Udontknow - Mo 02.12.02 14:05

Hi! :)

Das irgendein Fenster geschlossen wird, macht ja noch nichts. Erst wenn der Owner freigegeben wird, werden ja die untergeordneten Objekte freigegeben.

Dein Code im Destruktor wird nicht ausgeführt, weil eben der Count der Liste 0 ist (also sich die Komponenten bereits freigegeben haben, TComponentlist aktualisiert sich bei einer Freigabe automatisch).
Wenn ich das jetzt richtig verstanden habe, wunderst du dich, wieso Die Komponenten bereits freigegeben wurden.

Um das mal zu analysieren, setze doch einfach einen Haltepunkt auf den Destruktor einer der Komponenten, und schaue dir bei diesem Breakpoint dann den Aufrufstack an. Da kannst du ja dann wunderbar sehen, welche Aktion zum Freigeben der Komponente geführt hat.

Cu, :)
Udontknow

Nachtrag: OwnsObjects stammt von TObjectlist; Es beeinflusst nicht das Feld Owner (dies wird ja erst mit TComponent eingeführt!). Wenn OwnsObjects auf True steht, wird beim Zerstören der Liste auch dafür gesorgt, daß die Objekte, die in der Liste sind, verworfen werden. Das gleiche passiert z.B. dann auch durch Clear.
Wenn aber die Objekte bereits freigegeben wurden (z.B. weil die Objekte vom TComponent abstammen und ihr Owner freigegeben wurde), passiert eben nichts damit (zumindest in einer TComponentlist, in einer TObjectlist dürfte es Zugriffsschutzverletzungen geben).


LCS - Mo 02.12.02 14:26

Hi
Udontknow hat folgendes geschrieben:

Wenn ich das jetzt richtig verstanden habe, wunderst du dich, wieso Die Komponenten bereits freigegeben wurden.

Nein, eigentlich wunderte ich mich, warum mein Destructor nicht durchlaufen wurde.
Aber die Frage hat sich mittlerweile geklärt: Ich hab mich beim Debuggen prasslig angestellt user defined image Dein Hinweis auf den Aufrufstack hat dafür gesorgt, dass ich Lichter angehen. :D Und damit ist das Problem gelöst und die Frage beantwortet (mal Vorbild sei :mrgreen:)

Danke
Lothar