Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Speicherverwaltung bei Objektliste (https://www.delphipraxis.net/50523-speicherverwaltung-bei-objektliste.html)

messie 27. Jul 2005 07:48


Speicherverwaltung bei Objektliste
 
Moin,

eine Frage zur Speicherverwaltung: ich erzeuge lokal eine TObjectlist, die für einen Vergleich mit einigen Objekten gefüllt wird. Danach ist die Liste über. Beim nächsten Durchgang muß ich sie wieder neu erzeugen und mit neuen Objekten füllen.
Reicht es, wenn ich sie mit einem create neu erzeuge? Werden dann auch die Speicherzuweisungen zu den Objekten gekappt? Oder wird durch die lokale Definition der Speicherplatz beim Verlassen ohnehin freigegeben.

Ich brauche das nicht so oft, daß es zu Speicherlecks kommen könnte, aber wissen würde ich es trotzdem gerne.

Grüße, Messie

DP-Maintenance 27. Jul 2005 07:50

DP-Maintenance
 
Dieses Thema wurde von "alcaeus" von "Programmieren allgemein" nach "Object-Pascal / Delphi-Language" verschoben.
Ist wohl mehr ein Object-Pascal-Thema als was allgemeines ;)

barf00s 27. Jul 2005 07:53

Re: Speicherverwaltung bei Objektliste
 
wenn du die liste "häufiger" brauchst reichts ja wenn du sie außerhalb "createst" und dann zu anfang deiner füllroutine einfach "clearst" und in irgendeiner finalisierungsfunktion wieder "freest"

um 08:54: wenn du sie einfach nur jedesmal neuerstellst, bleiben die alten inhalte im speicher und kann so zu speicherlecks führen

[edit=alcaeus]Doppelpost zusammengefuehrt. In Zukunft bitte die Edit-Funktion verwenden. Mfg, alcaeus[/edit]

Mystic 27. Jul 2005 07:54

Re: Speicherverwaltung bei Objektliste
 
Du solltest also immer die Objekte und die TObjectList nachdem du sie benutzt hast wieder ordnungsgemäß freigeben.

alcaeus 27. Jul 2005 07:56

Re: Speicherverwaltung bei Objektliste
 
Hallo messie,

das TObjectList-Objekt musst du auf jeden Fall wieder freigeben. Das hier:
Delphi-Quellcode:
for i := 0 to 10 do
begin
  SomeObjList := TObjectList.Create();
  for j := 0 to 5 do
    SomeObjList.Add(TForm1.Create());
  DoSomething();
end;
erzeugt z.B. ein huebsches Speicherleck ;)

Du hast in diesem Fall mehrere Moeglichkeiten:
  1. Du erzeugst die ObjectList in jedem Schleifendurchgang, und gibst sie dort auch wieder frei:
    Delphi-Quellcode:
    for i := 0 to 10 do
    begin
      SomeObjList := TObjectList.Create();
      for j := 0 to 5 do
        SomeObjList.Add(TForm1.Create());
      DoSomething();
      SomeObjList.Free();
    end;
  2. Du erzeugst die ObjectList einmal, gibst sie erst nach der Schleife wieder frei, und loeschst sie am Schleifenbeginn:
    Delphi-Quellcode:
    for i := 0 to 10 do
     SomeObjList := TObjectList.Create();
    begin
      SomeObjList.Clear();
      for j := 0 to 5 do
        SomeObjList.Add(TForm1.Create());
      DoSomething();
    end;
    SomeObjList.Free();
    Diese Variante ist definitiv performanter, da du die Liste nicht jedesmal rauswirfst und neu erstellst.

Falls du die Objekte wirklich nur brauchst, solange die ObjectList existiert, kannst du den aOwnsObjects-Parameter beim Constructor verwenden. Gibst du dort ein True mit, so gilt die ObjectList als Besitzer der hinzugefuegten Objekte, und gibt diese bei einem Clear() oder Free() wieder frei. So musst du dich nicht um eventuelle ungueltige Referenzen bzw. Objektleichen im Speicher kuemmern.

Greetz
alcaeus

messie 27. Jul 2005 08:03

Re: Speicherverwaltung bei Objektliste
 
Das mit dem AOwnsObject hatte ich schon so gemacht. Die Liste am Ende der Routine mit free freizugeben fände ich auch gut, nur bleibt mir ein Problem (vielleicht ist dies mein Eigentliches): ich greife in einer anderen Routine ständig auf diese Liste zu. Bisher verwende ich eine if assigned-Anweisung, um zu Prüfen, ob es die Liste gibt. Nach einem free bleibt die Referenz in der Zuweisungsliste aber erhalten, also funzt if assigned hier nicht.

Grüße, Messie

alcaeus 27. Jul 2005 08:04

Re: Speicherverwaltung bei Objektliste
 
Hallo messie,

du musst in dem Fall einfach Delphi-Referenz durchsuchenFreeAndNil() anstatt Free() verwenden ;)

Greetz
alcaeus

messie 27. Jul 2005 08:11

Re: Speicherverwaltung bei Objektliste
 
Zitat:

Zitat von alcaeus
Hallo messie,

du musst in dem Fall einfach Delphi-Referenz durchsuchenFreeAndNil() anstatt Free() verwenden ;)

Greetz
alcaeus

Das gibt's bei einer TObjectlist nicht, jedenfalls nicht bei mir... Gibt es eine ALternative zur der PRüfung mit assign?

Grüße, Messie

barf00s 27. Jul 2005 08:33

Re: Speicherverwaltung bei Objektliste
 
@alceus

Zitat:

# Du erzeugst die ObjectList einmal, gibst sie erst nach der Schleife wieder frei, und loeschst sie am Schleifenbeginn:

Delphi-Quellcode:
for i := 0 to 10 do
SomeObjList := TObjectList.Create();
begin
  SomeObjList.Clear();
  for j := 0 to 5 do
    SomeObjList.Add(TForm1.Create());
  DoSomething();
end;
SomeObjList.Free();
Diese Variante ist definitiv performanter, da du die Liste nicht jedesmal rauswirfst und neu erstellst.
innerhalb der schleife erzeugst du jedesmal eine neue objectlist...

barf00s 27. Jul 2005 08:33

Re: Speicherverwaltung bei Objektliste
 
@messie

mit FreeAndNil() meinte alceus


das du anstelle von objList.Free lieber FreeAndNil(objList); verwenden sollst

messie 27. Jul 2005 10:46

Re: Speicherverwaltung bei Objektliste
 
Funzt irgendwie nicht. Egal was ich mache, ich bekomme sporadisch eine Zugriffsverletzung, auch wenn ich die Liste behalte und mit einem clear aufräume.

Delphi-Quellcode:
if WaitForSingleObject(Mutex1,100) = WAIT_OBJECT_0 then
  try
    if assigned(Objectlist1) then
      freeandnil(Objectlist1);
  finally
    ReleaseMutex(Mutex1);
  end;
Kann's damit zu tun haben, daß ich hier synchronisiert arbeite? Alle Zugriffe auf meine Objektliste sind mit dem Mutex geschützt und enthalten eine solche if assigned-Anweisung.

Grüße, Messie

barf00s 27. Jul 2005 10:58

Re: Speicherverwaltung bei Objektliste
 
naja du könntest deine objectlist mit nem lock schützen - dann brauchst nich mit mutexi rumtüdeln

Delphi-Quellcode:
type
  TJooObjectList = class(TObjectList)
  private
    FCriticalSection: TRTLCriticalSection;
  public
    constructor Create; override;
    destructor Destroy; override;
    function Lock: TObjectList;
    procedure UnLock;
  end;

imple...

constructor TJooObjectList.Create;
begin
  inherited Create;
  InitializeCriticalSection(FCriticalSection);
end;

destructor TJooObjectList.Destry;
begin
  DeleteCriticalSection(FCriticalSection);
  inherited Destroy;
end;

function TJooObjectList.Lock: TObjectList;
begin
  EnterCriticalSection(FCriticalSection);
  Result := Self;
end;

procedure TJooObjectList.Unlock;
begin
  LeaveCriticalSection(FCriticalSection);
end;






procedure tblah.foobar;
var
  xLock: TObjectList;

begin
  xLock := xObjList.Lock;
  try
    ...
  finally
    xObjList.UnLock;
  end;
end;

messie 27. Jul 2005 11:07

Re: Speicherverwaltung bei Objektliste
 
Ist eine Idee, die Mutexe geben mir aber die Möglichkeit, den zeitkritischen Teil zu bevorzugen.

Ein wenig komisch, daß ich solche Kontruktionen mit Mutexen zuhauf habe und die nur bei den ObjectList nicht funzen. Kann das sein, daß der Mutes zwar die Liste schützt, aber andere Programmteile auf die Objekte zugreifen können? Wie gesagt, die Zugrifssverletzung gibts nicht immer.

Grüße, Messie

barf00s 27. Jul 2005 11:09

Re: Speicherverwaltung bei Objektliste
 
dann bau den .Lock so um, da man da auf CriticalSections verzichtet und stattdessen mit dem mutexi tüddelt
aber um deine LISTE zu schützen, kopier sie einfach und benutz die kopie ;)

messie 27. Jul 2005 11:55

Re: Speicherverwaltung bei Objektliste
 
Zitat:

kopier sie einfach und benutz die kopie
genau das hab' ich ja von Anfang an getan. Leider habe ich dabei gepennt und nur die Referenz übergeben und keine echte Kopie erstellt:
Delphi-Quellcode:
LocalObjectlist.item[n] := ObjectList.item[n];
statt
Delphi-Quellcode:
LocalObjectList.add;
LocalObjectlist.item[n].Object1 := ObjectList.item[n].Object1;
Damit habe ich natürlich beim clear oder free auf nicht verfügbare Referenzen zugegriffen.

Ich bin halt nicht für die Objektorientierung gebaut.

Danke, Messie


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:40 Uhr.

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