Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Probleme mit Übergabe an TObjectlist (https://www.delphipraxis.net/47167-probleme-mit-uebergabe-tobjectlist.html)

messie 7. Jun 2005 11:37


Probleme mit Übergabe an TObjectlist
 
Hallo,

ich brauche mal ein paar Augen mehr, die meinen Quelltext besichtigen.
Ich sortiere Parameter die aus einem inifile gelesen werden und ordne sie einer Struktur aus Objektlisten und Objekten zu:

Delphi-Quellcode:

global:
 TParas = class(TObject)
   {verschiedene}
 end;

 TSubParameterList = class(TObjectList)
   {enthält Elemente vom Typ TParas}
 end;

 TParameterList = class(TObjectList)
   {enthält Elemente vom Typ TSubParameterList}
 end;

 TParameters = class(TObjectList)
   {enthält Elemente vom Typ TParameterList}
 end;

  var
    Parameters : TParameters;



procedure Sortierwas(filename : string);
var
  localpar : TParas;
  inifile : TInifile;

begin
  ParaFile := TIniFile.Create(filename);
  localpar := TParas.Create;
  Parameters := TParameters.Create;

  {Anlegen der Parameterlisten, nicht weiter wichtig}


  //Einlesen der Parameter

  repeat
    s := ParaFile.ReadString('Paras','Para' + intToStr(i),'');
    if s <> '' then
    begin
      localpar := ParaSort(s);
      Parameters.Items[localpar.ParaGroup].Items[0].add(TParas.Create);
      application.ProcessMessages;
      j := Parameters.Items[localpar.ParaGroup].Items[0].Count - 1;
      application.ProcessMessages;
      Parameters.Items[localpar.ParaGroup].Items[0].Items[j] := localpar;
      {hier die erste Debugausgabe ob die Übergabe ok ist...}
      ShowMessage(Parameters.Items[localpar.ParaGroup].Items[0].Items[j].name);
    end;  
  until s = '';

  ParaFile.Free;
  localpar.Free;

  {hier die zweite Debugausgabe ob die Übergabe ok ist...}
  for j := 0 to (result.Items[1].Items[0].Count) - 1 do
  begin
    ShowMessage(result.Items[1].Items[0].Items[j].name);
  end;
end;
Das jeweils letzte Element wird offensichtlich korrekt übergeben, ist aber später leer. Dies hängt davon ab, ob der Befehl "localpar.free" vewendet wird. Nehme ich den raus, bleiben die Elemente erhalten.

Was mach' ich da falsch??

Danke, Messie

teebee 7. Jun 2005 11:59

Re: Probleme mit Übergabe an TObjectlist
 
Zitat:

Zitat von messie
Delphi-Quellcode:
//Einlesen der Parameter

  repeat
    s := ParaFile.ReadString('Paras','Para' + intToStr(i),'');
    if s <> '' then
    begin
      localpar := ParaSort(s);
      Parameters.Items[localpar.ParaGroup].Items[0].add(TParas.Create);
      application.ProcessMessages;
      j := Parameters.Items[localpar.ParaGroup].Items[0].Count - 1;
      application.ProcessMessages;
      Parameters.Items[localpar.ParaGroup].Items[0].Items[j] := localpar; // <- hier weist Du der Objectlist das lokal erzeugte Objekt zu
      {hier die erste Debugausgabe ob die Übergabe ok ist...}
      ShowMessage(Parameters.Items[localpar.ParaGroup].Items[0].Items[j].name);
    end;  
  until s = '';

  ParaFile.Free;
  localpar.Free; // <- hier gibst Du das Objekt wieder frei

Du gibst das Objekt frei, das Du vorher zugewiesen hast. Und zwar nur das letzte, da Du die Freigabe außerhalb der Schleife vornimmmst. Die ObjectList speichert nur den Zeiger auf das Objekt, nicht das Objekt selbst.
Gib localpar einfach nicht selber frei, sondern überlasse das der ObjectList mit OwnsObjects := True (ist schon so per default).

Gruß, teebee

messie 7. Jun 2005 12:08

Re: Probleme mit Übergabe an TObjectlist
 
Hallo teebee,

ich glaub' ich hab's weitgehend verstanden: ich übergebe ja nicht die Inhalte, sondern das Objekt selbst. So weit, so gut: aber ich erzeuge das lokale Objekt jedesmal in der Routine. Ist das nicht riskant (Speicherleck o.ä)?

Komisch, ich habe das Objekt jetzt einfach gar nicht erzeugt sondern wie eine Variable behandelt. Damit klappt es. Kann mir jemand erklären, warum?

Grüße, Messie

Muetze1 7. Jun 2005 12:17

Re: Probleme mit Übergabe an TObjectlist
 
Moin!

Wieso denn? Du übergibst doch das jeweils erzeugte Objekt als Referenz an die Objektliste und diese kann dann doch auf jedes einzelne in der Schleife erzeugte Element zugreifen. Und wie teebee schon sagte, hat die Objektliste standardmässig OwnsObject auf true, was bedeutet das sie beim delete und Clear und Free alle in ihr gehaltenen Objektreferenzen freigibt - also auch alle in der Schleife erzeugten Instanzen. Somit gibt es auch keine Speicherlecks.

Zitat:

Zitat von messie
Komisch, ich habe das Objekt jetzt einfach gar nicht erzeugt sondern wie eine Variable behandelt. Damit klappt es. Kann mir jemand erklären, warum?

Das wäre Zufall, weil die Variable eine lokale Variable ist und somit einen zufälligen Wert beinhaltet. Dieser wird beim Zugriff als Adresse interpretiert und du hast die Daten die du dem Objekt zugewiesen hast irgendwo im Speicher der Applikation hingeschrieben. Damit überschreibst du dir wiederrum andere Dinge...

MfG
Muetze1

messie 7. Jun 2005 12:46

Re: Probleme mit Übergabe an TObjectlist
 
Noch mal, damit ich es richtig verstehe: das Objekt wird also als Ganzes übergeben? Es ist also nach der Übergabe nicht mehr als unabhängiges Objekt vorhanden?

Grüße, Messie

Muetze1 7. Jun 2005 14:01

Re: Probleme mit Übergabe an TObjectlist
 
Moin!

Nein. Also, mal ein wenig umfangreicher:

Wenn du ein Objekt irgendwo mit Create instanziierst, dann wird ein Speicherblock angelegt im Speicher wo das Objekt liegt. Das Create gibt nur die Adresse zurück, wo es liegt (ein Pointer). Eine Objektvariable ist intern eigentlich nur ein Pointer auf das Objekt selber. Wenn du nun einer anderen Variable das Objekt zuweist, dann bekommt die zweite Variable einfach nur die Adresse, wo im Speicher das Objekt gibt. Die Objektliste merkt sich auch nur die Adressen der Objekte, wo sie liegen.

Daher auch dein Problem: Beispiel:

Delphi-Quellcode:
Var
  a, b : TObject;
Begin
  a := TObject.Create;
  b := a;

  // Das Objekt liegt irgendwo im Speicher
  // a und b zeigen auf das gleiche Objekt

  a.Free; // nun hast du das Objekt freigegeben - aber: a und b zeigen noch auf die alte Stelle im Speicher wo das Objekt lag

End;
MfG
Muetze1

messie 7. Jun 2005 14:30

Re: Probleme mit Übergabe an TObjectlist
 
Genau das wollte ich mit meiner Frage ausdrücken: der Speicher wird nur einmal belegt, im Gegensatz zur Benutzung zweier Variablen...

Weils so schön ist, habe ich dann aus meinem Code
Delphi-Quellcode:
 Parameters.Items[localpar.ParaGroup].Items[0].add(TParas.Create);
 j := Parameters.Items[localpar.ParaGroup].Items[0].Count - 1;
 Parameters.Items[localpar.ParaGroup].Items[0].Items[j] := localpar
Delphi-Quellcode:
 Parameters.Items[localpar.ParaGroup].Items[0].add(localpar);
gemacht. Denn das create im add ist ja dann überflüssig.

Grüße, Messie

Muetze1 7. Jun 2005 14:42

Re: Probleme mit Übergabe an TObjectlist
 
Moin!

Zitat:

Zitat von messie
Denn das create im add ist ja dann überflüssig.

Nein, weil dann hast du nur eine Instanz und die du dann x-mal hinzufügst zu der TObjectList. Und daher ist dann am Ende jedes Objekt deiner Objektliste das gleiche Objekt, weil alle nur auf das gleiche Objekt im Speicher zeigen. Dieses eine Objekt kann sich auch nur einmal die Daten merken. Daher wirst du in jedem Eintrag der Objektliste das gleiche Objekt finden, was auch nur die Daten des zuletzt eingefügten Objekts hat. Und wenn du auch nur einen Eintrag aus der Objektliste entfernst, dann wird das Objekt freigegeben und alle Einträge zeigen auf leeren Speicher und somit bekommst du eine AV beim Zugriff...

MfG
Muetze1

messie 7. Jun 2005 14:56

Re: Probleme mit Übergabe an TObjectlist
 
OK!

Danke für die Tipps.

Messie


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:23 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz