Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Dispose: Pointer oder Object? (https://www.delphipraxis.net/128634-dispose-pointer-oder-object.html)

PeterPanino 3. Feb 2009 03:20


Dispose: Pointer oder Object?
 
Hallo, ich habe eine Frage zu Dispose:

Ich hänge an die Nodes einer TreeView Record-Objekte an:

Delphi-Quellcode:
type
  PNoteRec = ^TNoteRec;
  TNoteRec = record
    Caption: string;
    ID: string;
  end;

implementation

procedure TformMain.BaumElementHinzufuegen(const TV: TTreeView);
var
  NewNode: TTreeNode;
  NoteRecPtr: PNoteRec;
begin
  New(NoteRecPtr);
  NoteRecPtr^.Caption := 'XYZ';
  NoteRecPtr^.ID := 'ZYX';
  NewNode := TV.Items.AddChildObject(TV.Items[0], 'XYZ', NoteRecPtr);
  // ...
Nun möchte ich den reservierten Speicher bei Programmende freigeben:

Delphi-Quellcode:
Dispose(TV.Items[j].Data);
oder:

Delphi-Quellcode:
Dispose(PNoteRec(TV.Items[j].Data));
Welche der beiden Dispose-Varianten muss ich verwenden?

Union 3. Feb 2009 03:32

Re: Dispose: Pointer oder Object?
 
In dem Fall kannst Du die Typinformation weglassen. Das Speichermanagement funktioniert.

jbg 3. Feb 2009 11:24

Re: Dispose: Pointer oder Object?
 
Zitat:

Zitat von Union
In dem Fall kannst Du die Typinformation weglassen. Das Speichermanagement funktioniert.

Von wegen. Wenn er den Typecast weg lässt, dann wird das "Dispose" vom Compiler in ein "FreeMem" umgeschrieben und die beiden Strings (Managed-Datentypen) bleiben im Speicher liegen, da nur die beiden Zeiger auf die Strings mit dem FreeMem freigegeben werden, nicht aber die Strings selbst.

himitsu 3. Feb 2009 11:30

Re: Dispose: Pointer oder Object?
 
Zitat:

Zitat von PeterPanino
Nun möchte ich den reservierten Speicher bei Programmende freigeben:

Hat die TreeView nicht ein Ereignis für NodeWirdFreigegeben?
Also ich würde das Freigeben dann dort drin machen.


Und jbg hat Recht.

Union 3. Feb 2009 11:31

Re: Dispose: Pointer oder Object?
 
Und wieso findet dann Memcheck das so erzeugte vermeintliche Speicherleck nicht? Ich habe das ganz ohne Dispose getestet und natürlcih gab es ein Leck. Beide Varianten mit Dispose (mit / ohne Typecast) brachten kein Leck.

himitsu 3. Feb 2009 11:32

Re: Dispose: Pointer oder Object?
 
Hmmm, eigentlich müßte ein Leck entstehen ... wie hast'n das getestet?
Etwas Code wäre nett, nicht daß du über einen der Sonderfälle bei den Strings gestolpert bist :angel2:

Union 3. Feb 2009 11:40

Re: Dispose: Pointer oder Object?
 
Mit Eurekalog und eingeschaltetem Memcheck. Allerdings habe ich nur ein NoteRec erzeugt mit den ersten 3 Zeilen der Prozedur:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  NoteRecPtr: PNoteRec;
begin
  New(NoteRecPtr);
  NoteRecPtr^.Caption := 'XYZ';
  NoteRecPtr^.ID := 'ZYX';
  Dispose(NoteRecPtr);
end;

himitsu 3. Feb 2009 11:46

Re: Dispose: Pointer oder Object?
 
'XYZ' ist eine untypisierte Konstante und bei Strings liegen untypisierte Konstanten nicht im RAM.

versuch's mal statt mit 'ner Konstante über eine dieser 3 Varianten :mrgreen:
Delphi-Quellcode:
NoteRecPtr^.Caption := IntToStr(123);

SetLength(NoteRecPtr^.Caption, 3);

NoteRecPtr^.ID := 'XYz';
NoteRecPtr^.ID[3] := 'Z';

PeterPanino 3. Feb 2009 13:12

Re: Dispose: Pointer oder Object?
 
Komisch, wenn ich NACH dem Dispose die Record-Daten abfrage, bekomme ich bei beiden Dispose-Arten ein jeweils anderes Ergebnis:

Hier werden im zweiten MessageDlg die Record-Daten weiterhin angezeigt:

Delphi-Quellcode:
MessageDlg(PNoteRec(TL.Items[j].Data)^.Caption, mtInformation, [mbOK], 0);
Dispose(TL.Items[j].Data);
MessageDlg(PNoteRec(TL.Items[j].Data)^.Caption, mtInformation, [mbOK], 0);
Und hier wird im zweiten MessageDlg gähnende Leere angezeigt:

Delphi-Quellcode:
MessageDlg(PNoteRec(TL.Items[j].Data)^.Caption, mtInformation, [mbOK], 0);
Dispose(PNoteRec(TL.Items[j].Data));
MessageDlg(PNoteRec(TL.Items[j].Data)^.Caption, mtInformation, [mbOK], 0);
Bei beiden Dispose-Arten entsteht jedoch durch den Zugriffsversuch auf die Record-Daten NACH dem Dispose kein (Zeiger-)Fehler, obwohl mit Dispose der Speicher bzw. der Zeiger auf den Speicher ja freigegeben worden sein müsste!?

himitsu 3. Feb 2009 13:27

Re: Dispose: Pointer oder Object?
 
nach dem Freigeben von Speicher sollte man eh nicht mehr versuchen darauf zuzugreifen.

Nur weil mit Dispose (oder sonstwas) spehcer freigegeben wurde, kann ers sein, daß dieser dennoch vom Speichermanager reserviert ist (schlimmstenfalls wird dieser Speicher sogar inzwischen für was Anderes verwendet)

bei Dispose werden die Strings freigegeben, wobei der interne Stringzeiger nun auf NIL steht ... drum zeigt das Zweite nichts mehr an, wärend (wie schon gesagt) Dispose ohne Typeninformationen die Strings nicht freigibt und auch nicht den Record nullt ... drum kannst du beim Ersten noch alles auslesen (das erwähnte Speicherleck)

PS: wenn der Speichermanager den ganzen Speicherbereich freigegeben hätte, dann hättest du bei beiden Varianten eine Zugriffsverletzung geerntet.
(der Speichermanager reserviert große Speicherbereiche und gibt diesen in kleineren Portionen weiter ... ist optimaler so)


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:53 Uhr.
Seite 1 von 2  1 2      

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