Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Record "finalisieren" (https://www.delphipraxis.net/179793-record-finalisieren.html)

CocoPops 2. Apr 2014 14:02

Record "finalisieren"
 
Gemeinde.

Es tut mir schrecklich leid, wenn ich nicht die richtigen Ausdrücke und Worte finde für mein Problem.

Ich habe ein packed Record, etwa so:
Delphi-Quellcode:
type
 PData = ^TData;

 TData = packed record
   sBeispielVar: String;
end;
und folgendermaßen erzeuge ich einen neuen Datensatz, wenn erforderlich und speichere ihn/einen Verweis zum ihm (?) in einer TList:
Delphi-Quellcode:
var
 Data: PData:
begin
 New(Data);
 Data^.sBeispielVar := 'Test';
 DataList.Add(Data);
end;
Zuvor habe ich einen Eintrag mit
Delphi-Quellcode:
DataList.Delete(X);
gelöscht und Data finalisiert:
Delphi-Quellcode:
finalize(Data^);
.
Aber finalize scheint nicht thread-safe zu sein.

Die Frage ist: wird bei
Delphi-Quellcode:
DataList.Delete(X);
der komplette Datensatz Data, der an dieser Stelle X gespeichert ist, mit gelöscht?

Neutral General 2. Apr 2014 14:05

AW: Record "finalisieren"
 
Hallo,

Bedenke dass du auch Dispose aufrufen musst (oder macht das die Liste beim Delete?).

Wie ich es machen würde:
Code:
Finalize(DataList[X]^);
Dispose(DataList[X]);
DataList.Delete(X);

Namenloser 2. Apr 2014 14:09

AW: Record "finalisieren"
 
Dispose ruft übrigens intern schon von sich aus Finalize auf, hatte ich glaub ich mal rausgefunden.

CocoPops 2. Apr 2014 14:13

AW: Record "finalisieren"
 
Sehr interessant. Das scheint wunderbar, selbst im TThread, zu funktionieren.

Warum war denn Finalize(Data^) falsch?

Ich habe mit mal den Code von Dispose rausgesucht:
Delphi-Quellcode:
procedure _Dispose(P: Pointer; TypeInfo: Pointer);
{$IFDEF PUREPASCAL}
begin
  _Finalize(P, TypeInfo);
  FreeMem(P);
end;
{$ELSE}
asm
        { ->   EAX    Pointer to object to be disposed       }
        {       EDX    Pointer to type info                   }

{$IFDEF ALIGN_STACK}
        SUB    ESP, 8
{$ENDIF ALIGN_STACK}
        PUSH   EAX
        CALL   _Finalize
        POP    EAX
{$IFDEF ALIGN_STACK}
        SUB    ESP, 4
{$ENDIF ALIGN_STACK}
        CALL   _FreeMem
{$IFDEF ALIGN_STACK}
        ADD    ESP, 12
{$ENDIF ALIGN_STACK}
end;
{$ENDIF !PUREPASCAL}
Finalize ist wirklich vertreten, aber mit einer Bedingung verknüpft.

Und in der selben Unit wird, wenn Dispose(P); aufgerufen wird, auch niemals Finalize aufgerufen.
Demnach scheint Finalize wirklich immer aufgerufen zu werden, wenn man Dispose aufruft.

himitsu 2. Apr 2014 14:37

AW: Record "finalisieren"
 
GetMem und FreeMem = ohne Initialize und Finalize
New und Dispose = mit Initialize und Finalize


Setzt Finalize den Speicher eigentlich auch auf 0/nil, oder gibt es die verlinkten Speicher "nur" frei?
Wenn nicht auf nil gesetzt wird, dann ist ein "doppelter" Aufruf von Finalize falsch und kann/wird zu netten Fehlern führen.



Welche Delphi-Version? (es kann nie schaden das im Profil anzugeben, oder zumindestens in den Posts)
Ab D2009 könnte man auch eine generischen Liste verwenden und das New/Dispose wegzulassen.
Jenachdem wie oft die Records umgeschaufelt oder später verändert werden.

Da hier eh mit Pointer gearbeitet wird und wenn das "jenachdem" nicht zutrifft, dann doch eher eine generische Liste, mit einem Data-Objekt, statt dem Record.


Zitat:

Delphi-Quellcode:
Data^.sBeispielVar

PS: Delphi kann das auch implizit dereferenzieren, wenn ein Punkt folgt.
Delphi-Quellcode:
Data.sBeispielVar

himitsu 2. Apr 2014 14:41

AW: Record "finalisieren"
 
[edit] Doppelpost gelöscht

Namenloser 2. Apr 2014 14:47

AW: Record "finalisieren"
 
Zitat:

Zitat von himitsu (Beitrag 1254406)
Setzt Finalize den Speicher eigentlich auch auf 0/nil, oder gibt es die verlinkten Speicher "nur" frei?
Wenn nicht auf nil gesetzt wird, dann ist ein "doppelter" Aufruf von Finalize falsch und kann/wird zu netten Fehlern führen.

Finalize mehrfach aufzurufen macht soweit ich weiß nichts, also nehme ich an, dass die entsprechenden Speicherstellen auf nil gesetzt werden.

Neutral General 2. Apr 2014 15:41

AW: Record "finalisieren"
 
Ich glaube das Problem war dass er Dispose einfach gar nicht aufgerufen hat.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:43 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