Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi SetLength(dyn. array, 0) vs. Finalize() vs. nil (https://www.delphipraxis.net/56393-setlength-dyn-array-0-vs-finalize-vs-nil.html)

Nogge 4. Nov 2005 22:45


SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Hallo Community,
Ich habe mal im Forum rechergiert, welche Möglichkeiten es gibt, dyn. arrays freizugeben. Dabei bin ich auf die o.g. Prozeduren bzw. nil gestoßen und bin jetzt leicht verwirrt. Ich zitiere einfach mal die verschiedenen Aussagen:
Zitat:

Zitat von Muetze1
Ich hatte früher öfters irgendwo und sporadisch Speicherlecks und z.T. Zugriffsverletzungen ohne Grund - bis ich diese beiden Funktionen eingesetzt habe. Zum grundlegenden Einsatz:

- Vor der Verwendung des Arrays einmalig Initialize() (also auch vor dem SetLength())
- Nach der Verwendung des Arrays einmalig Finalize() (also zuvor SetLength(arr, 0))

Zitat:

Zitat von sakura
Delphi-Quellcode:
SetLength(MyFlexibleArray, 20);
allocates an array of 20 reals, indexed 0 to 19. Dynamic arrays are always integer-indexed, always starting from 0.
Dynamic-array variables are implicitly pointers and are managed by the same reference-counting technique used for long strings. To deallocate a dynamic array, assign nil to a variable that references the array or pass the variable to Finalize; either of these methods disposes of the array, provided there are no other references to it. Dynamic arrays of length 0 have the value nil. Do not apply the dereference operator (^) to a dynamic-array variable or pass it to the New or Dispose procedure.

Zitat:

Zitat von Chewie
Sie bewirken das gleiche, wobei die nil-Variante ein paar Takte schneller ist. Bei der Zuweisung an nil wird gleich DynArrayClear aufgerufen, bei der Variante mit SetLength wird erst DynArraySetLength aufgerufen, welches dann wiederum besagtes DynArrayClear aufruft.

Nach dem ganzen Hin- und Her: Nehmen wir mal zwei Beispiele:
Delphi-Quellcode:
type
  TStringArray = array of String;
var
  Partition : array of TTreeNode;
  Dirs      : TStringArray;
  [...]
  SetLength(Partition,10);
  SetLength(Dirs,3);
  [...]
  // Freigeben beider dyn. arrays
Wie sollte ich jetzt die beiden dyn. arrays sauber freigeben, sodass der gesamte Speicherbereich wieder an Windows übergeben wird?
Btw: Wie müsste ich ein array of "record" korrekt freigeben, wenn dieser u.a. Short- bzw. LongStrings (= unbegrenzte Angabe), Integers und TreeNodes enthalten würde?

Muetze1 5. Nov 2005 14:29

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von Nogge
..., sodass der gesamte Speicherbereich wieder an Windows übergeben wird?

Nur eine kurze Anmerkung zu dieser Frage und nicht zum Problem an sich: Der Speicherbereich wird nicht an Windows sondern an den Heap zurück gegeben. Ob der Heap sich verkleinert und Teile an Windows zurück gibt, das hängt sehr stark vom verwendeten Speichermanager ab - die meisten verkleinern sich nicht mehr (schon als verwaltungstechnischen Gründen).

Zum Thema:

Ich kann zu meiner vorherigen Aussage trotzdem nur nochmals ausführen, was ich festgestellt habe:

1. Dynamischen Arrays einfach NIL zuweisen gibt diese nicht sauber frei und werden als verlorener Speicher bei Speichertestern ausgegeben (Delphi 4 und Delphi 5)
2. lokale dynamische Arrays in Proceduren hinterlassen !sporadisch! Speicherlecks, wenn nach dem SetLength() kein Finalize() kommt (Delphi 4)
3. direktes anwenden von Finalize auf ein dynamisches Array führt zu einer ungenügenden Array Freigabe, es bleiben im Schnitt 8 Bytes nicht freigegeben zurück (Delphi 5).

Bei höheren Delphiversionen mag das alles klappen und ein vernünftiger Weg sein.

Nogge 5. Nov 2005 15:18

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Also nach deiner Auffassung sollte ich bei dem Beispiel die dyn. arrays so freigeben?
Delphi-Quellcode:
SetLength(Partition,0);
SetLength(Dirs,0);
Finalize(Partition);
Finalize(Dirs);
Muss ich nicht die einzelnen TreeNodes aus dem array "Partition" seperat freigeben oder übernimmt gerade Finalize() diese Aufgabe für mich?

marabu 5. Nov 2005 15:45

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Ein dynamisches Array mit dem base type TTreeNode ist recht ungewöhnlich. Grundsätzlich lebt ein TTreeNode in der Obhut von TTreeNodes und dieser Container verwaltet die Nodes von der Wiege bis zur Bahre. Finalize(), angewandt auf das dynamische array, weiß nichts von diesem Doppelleben der Nodes und darf auch gar nichts darüber wissen.

Grüße vom marabu

Nogge 5. Nov 2005 16:21

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Jo, deine Aussage war richtig. Es ist wirklich ungewöhnlich und sinnlos, solch ein array zu deklarieren, wie ich in meinem Code bemerkt habe. Habe das jetzt korrigiert.
Zu Finalize(): Diese Prozedur wird also nur auf Variablen mit undefinierbarer Länge angewandt, wie z.B. auf long-strings, variants usw.? D.h. es gibt keinen Grund, diese Prozedur auf array of Extended oder array of String[200] bzw. Shortstring loszulassen, richtig?
Noch mal zu records:
Delphi-Quellcode:
type
  PGroupData = ^TGroupData;
  TGroupData = record
    GroupID     : Word;
    ShouldExpand : Boolean;
    S           : String;
  end;
var
  TestArrayT : array of TGroupData; // wird eher selten benutzt, nicht wahr?
  TestArrayP : array of PGroupData;
Da in diesem record eine Variable mit undefinierter Länge (= String) enthalten ist, müsste ich diesen doch beim Freigeben des arrays mit Finalize() leeren, oder? Und wenn ja, wie genau?
Wenn ich jetzt falsch liege, erklärt mir bitte das Gegenteil mithilfe der Beipiele. Das hilft mir ungemein.

marabu 5. Nov 2005 16:56

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von Nogge
Zu Finalize(): Diese Prozedur wird also nur auf Variablen mit undefinierbarer Länge angewandt, wie z.B. auf long-strings, variants usw.?

Ich würde nicht von undefinierbarer Länge sprechen, sondern von speziellen dynamischen Variablen. In Delphi werden dynamische Variablen normalerweise mit New() und Dispose() verwaltet. Mit den long strings, den variants und den interfaces (die Aufzählung ist nicht vollständig) hat eine neue Klasse "dynamischer Variablen" in Object Pascal Einzug gehalten, bei der auch oft von compiler magic gesprochen wird. Es sind dynamische Variablen, bei denen nicht du es bist, der New() und Dispose() aufruft. Das Laufzeitsystem weiß, wann es Speicher braucht und wann es ihn wieder freigeben muss - wenn du ihm nicht in die Quere kommst.

Zitat:

Zitat von Nogge
D.h. es gibt keinen Grund, diese Prozedur auf array of Extended oder array of String[200] bzw. Shortstring loszulassen, richtig?

Falsch, aber das müsstest du selbst erkennen, wenn du meinen Beitrag bis hierhin gelesen hast. Dynamische Arrays gehören halt auch zu dieser speziellen Variablen-Klasse.

Delphi-Quellcode:
type
  PGroupData = ^TGroupData;
  TGroupData = record
    GroupID     : Word;
    ShouldExpand : Boolean;
    S           : String;
  end;
var
  TestArrayT : array of TGroupData; // wird eher selten benutzt, nicht wahr?
  TestArrayP : array of PGroupData;
Zitat:

Zitat von Nogge
Da in diesem record eine Variable mit undefinierter Länge (= String) enthalten ist, müsste ich diesen doch beim Freigeben des arrays mit Finalize() leeren, oder? Und wenn ja, wie genau?

Finalize(TestArrayT, Length(TestArrayT)) sorgt dafür, dass für alle Elemente deines Arrays die reference counts dekrementiert werden können und der garbage collector seines Amtes walten kann.

Für deinen zweiten Array-Typ bin ich im Augenblick überfragt. Ich vermute sehr stark, dass keine Finalisierung statt finden wird, aber ich müsste es untersuchen um sicher zu sein.

marabu

Nogge 5. Nov 2005 19:33

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Vielen Dank für die detailierten und klärenden Erläuterungen, Muetze1 und marabu.
Zusammenfassend kann man also sagen:
Mit SetLength initialisierte dyn. arrays sollten mit (in der Reihenfolge)
1.) SetLength(array, 0);
und
2a.) Finalize(array);
bzw.
2b.) Finalize(array, Length(array));
freigegeben werden.
2a) wird benutzt, wenn ein array of vordefinierte Typen (= string, Integer, Real, Boolean usw.) verwendet wird.
2b) wird benutzt, wenn ein array of TRecord verwendet wird.

Erbitte Bestätigung für diese Zusammenfassung. Danke.

marabu 5. Nov 2005 19:52

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Ich sehe keinen Interpretationsspielraum in dieser Frage. "Dynamische Typen" sind die internen Typen LongString, WideString, Variant, Array, Record, Interface und DynArray. Wenn v eine Variable ist und ihr Typ zu den zuvor genannten zählt, dann ist Finalize(v) bzw. Finalize(v, Length(v)) angesagt. Bei Arrays folgt dann SetLength(v, 0), bei den anderen Typen v := nil - so ist man auf der sicheren Seite.

marabu

Nogge 5. Nov 2005 23:08

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Ok, ok...
eins noch: Gerade an dieser Stelle kreuzen sich 2 Meinungen:
Zitat:

Zitat von marabu
Wenn v eine Variable ist und ihr Typ zu den zuvor genannten zählt, dann ist Finalize(v) bzw. Finalize(v, Length(v)) angesagt. Bei Arrays folgt dann SetLength(v, 0).

Zitat:

Zitat von Muetze1
2. lokale dynamische Arrays in Proceduren hinterlassen !sporadisch! Speicherlecks, wenn nach dem SetLength() kein Finalize() kommt (Delphi 4).

Sry, wenn ich dich vllt nerve, aber kommt Finalize() jetzt hinter oder vor SetLength()?

marabu 6. Nov 2005 07:46

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Hallo Nogge,

wenn SetLength(v, 0) zuerst ausgeführt wird, dann kommt Finalize(v, Length(v)) doch nach der Feier.

Delphi-Quellcode:
type
  TItem = packed record
    Name: string;
    Amount: integer;
  end;

var
  Items: array of TItem;
  i: integer;

begin
  // es werden 3 mal 8 Byte vom heap besorgt
  SetLength(Items, 3);

  // die einzelnen Items werden initialisert
  for i := Low(Items) to High(Items) do
    with Items[i] do
    begin
      // der pointer "Name" wird auf einen dynamischen
      // Speicherblock gesetzt, der 6 Byte Nutzdaten zzgl.
      // Verwaltungsinformationen (Längenzähler, term char, etc.
      // umfasst.
      Name := 'Name-' + IntToStr(Succ(i));
      // nativer Datentyp, kein heap beteiligt
      Amount := Succ(Random(5));
    end;
  end;

  // Alle Zeiger "Name" werden auf nil gesetzt
  // der garbage collector beobachtet den auf
  // 0 gehenden refence count und deallokiert
  // den von den strings auf dem heap belegten Speicher
  Finalize(Items, Length(Items));

  // Die 3 * 8 Byte müssen auch noch an den heap
  // zurückgegeben werden.
  SetLength(Items, 0);

end;
Sonntagsgrüße vom marabu

jbg 6. Nov 2005 09:57

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von marabu
wenn SetLength(v, 0) zuerst ausgeführt wird, dann kommt Finalize(v, Length(v)) doch nach der Feier.

Hat sich eigentlich schon irgendwer die SetLength Funktion für dyn. Arrays in der System-Unit angeschaut? Anscheinend nicht.
Das hier diskutierte kommt mir mehr so vor:
Delphi-Quellcode:
MyObj := TMyObj.Create;
...
MyObj.Free;
MyObj := nil;
MyObj.Free;
MyObj := nil;
MyObj.Free;
MyObj := nil;
MyObj.Free;
MyObj := nil;
MyObj.Free;
MyObj := nil;
MyObj.Free;
MyObj := nil;
So jetzt kann ich mir sicher sein, dass MyObj auch wirklich freigegeben wurde.

Finalize muss man nur Aufrufen, wenn man auf New und Dispose bei Zeigern auf Records verzichtet, also die Compile-Magic umgeht.
Delphi-Quellcode:
var P: PMyRec;
begin
  New(P);
  ...
  Finalize(P);
  FreeMem(P); // Statt Dispose gleich direkt freigeben, macht zwar keinen Sinn, aber wers so will
end;
Bei dynamischen Arrays übernimmt der Compiler genauso wie bei Strings automatisch die Initialisierung und Finalisierung. Da muss man nichts selbst einfügen. Das Delphi 4 da noch einen Bug hat, der von einem Update dann aber behoben wurde (wenn ich mich recht erinnere), heißt noch lange nicht, dass Delphi 5, 6, 7, 8, 2005 diesen Bug auch haben.

Nogge 6. Nov 2005 10:18

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Moin, Ich habe deinen Satz (mit "Feier" usw.) zwar nicht verstanden, aber dafür den Code :-D Nur woher weiß SetLength(Items,0) anfangs, dass genau 8 Bytes pro TItem benötigt werden? Entstehen diese 8 bzw. 7 Bytes nicht erst bei der Zuweisung der einzelnen Strings?
@jbg: Und noch eine andere Meinung...Ich habe ja extra die unterschiedlichen Ansichten am Anfang zitiert, um meine Verwirrung darzustellen. Einer der Profis meint dies, der andere dementiert das wieder und interpretiert etwas anderes in die Delphi-Hilfe hinein...

Flocke 6. Nov 2005 10:33

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von Nogge
Nur woher weiß SetLength(Items,0) anfangs, dass genau 8 Bytes pro TItem benötigt werden?

Dazu benutzt Delphi ebenfalls "Compiler-Magic", nämlich die RTTI. Intern wird nämlich eine Routine aus System.pas aufgerufen, die als zusätzlichen Parameter die Typbeschreibung der Elemente des Arrays bekommt. So kann SetLength auch das Finalize (für gelöschte) und Initialize (für hinzugekommene) Elemente automatisch machen.
Das gilt (so weit ich weiß) sogar für verschachtelte Typen, also für Arrays von einem Record das jeweils wieder ein dynamisches Array enthält.

marabu 6. Nov 2005 14:14

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von Nogge
Nur woher weiß SetLength(Items,0) anfangs, dass genau 8 Bytes pro TItem benötigt werden?

Du kannst dir das so vorstellen, dass bei der dynamischen Speicheranforderung für einen string der Länge 100 zusätzliche Bytes für Verwaltungsinformationen aufgerechnet werden. Bevor der Zeiger auf den string zurückgegeben wird, wird er um die Größe der Verwaltungsinformation inkrementiert. Veränderst du den Bereich vor dem string, so kommt Delphi aus dem Tritt.

Ausgelöst durch den Beitrag von jbg habe ich mich mit deinem TestArrayT und TestArrayP intensiver beschäftigt.

Zitat:

Zitat von jbg
Finalize muss man nur Aufrufen, wenn man auf New und Dispose bei Zeigern auf Records verzichtet, also die Compile-Magic umgeht.

Das gibt der Hilfetext von Delphi 7 (deutsche Fassung) so nicht her. In dem Bestreben sich mögliche Änderungen an der Implementierung der dynamischen Speicherverwaltung offen zu halten, legt uns die Hilfe den Einsatz von Finalize immer dann nahe, wenn eine dynamische Variable (die selbst wieder dynamische Variablen enthält) nicht mit Dispose() freigegeben wird. Auf die Tatsache, dass innerhalb der aktuellen SetLength()-Implementierung unter gewissen Umständen bereits ein Finalize() ausgeführt wird, möchte uns Borland aus nachvollziehbaren Gründen nicht stoßen.

Zitat:

Zitat von jbg
Bei dynamischen Arrays übernimmt der Compiler genauso wie bei Strings automatisch die Initialisierung und Finalisierung.

Speziell die beiden Testfälle von Nogge verdeutlichen aus meiner Sicht, warum man das von Borland recht gut umgesetzte Grundprinzip des information hiding nicht in Frage stellen sollte. Bei der Freigabe über SetLength(TestArrayT, 0) wird die Finalisierung implizit durchgeführt, bei SetLength(TestArrayP, 0) nicht.

In meinem vorigen Beitrag habe ich versucht zu erklären, warum ein Finalize(v, 10) nach einem SetLength(v, 0) fehl am Platze ist (wer zu spät kommt, der kommt nach der Feier - alte Redensart). Das Beispiel ist frei von Seiteneffekten und hoffentlich leicht nachvollziehbar gewesen. Niemand sollte sich verplichtet fühlen dem Beispiel zu folgen, wenn er es nicht verstanden hat oder gar einen besseren Weg kennt.

Freundliche Grüße vom marabu


PS: Auf einen Fehler von mir hat mich tommie-lie per PN aufmerksam gemacht:

Zitat:

Zitat von marabu
Zitat:

Zitat von Nogge
D.h. es gibt keinen Grund, diese Prozedur auf array of Extended oder array of String[200] bzw. Shortstring loszulassen, richtig?

Falsch, aber das müsstest du selbst erkennen, wenn du meinen Beitrag bis hierhin gelesen hast. Dynamische Arrays gehören halt auch zu dieser speziellen Variablen-Klasse.

Natürlich muss in diesen Fällen kein Finalize() verwendet werden, da ja keine dynamischen Typen als Basistyp für das Array-Element verwendet werden. Sorry für die Verwirrung, die ich eventuell mit dieser Aussage gestiftet habe. Schön, dass immer jemand Korrektur liest.

Danke, Thomas (tommie-lie).

tommie-lie 6. Nov 2005 14:57

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von marabu
Auf die Tatsache, dass innerhalb der aktuellen SetLength()-Implementierung unter gewissen Umständen bereits ein Finalize() ausgeführt wird, möchte uns Borland aus nachvollziehbaren Gründen nicht stoßen.

So nachvollziehbar finde ich persönlich das gar nicht. SetLength() auf dynamische Arrays mit nicht-primitiven, dynamischen Datentypen legt mir immerhin vollständig initialisierte Array-Elemente in die Hand. Bei einem wiederholten SetLength()-Aufruf, bei dem die Länge des Arrays vrkürzt wird, erwarte ich, daß die Elemente, die hinten rausfallen, ebenso sauber deinitialisiert werden, wie sie vorher initialisiert wurden. Muss ich mich in irgendeinem Fall selbst um das finalize() kümmern, hat das IMHO in der Hilfe zu stehen.

Zitat:

Zitat von marabu
Bei der Freigabe über SetLength(TestArrayT, 0) wird die Finalisierung implizit durchgeführt, bei SetLength(TestArrayP, 0) nicht.

Verhält sich für mich wie erwartet, da ^TSomeType (PSomeType) kein dynamischer Typ ist, sondern lediglich ein Integer, also ein primitiver Typ. Das Array muss also weder initialisiert werden, noch finalisiert (der Fall wäre der gleiche wie in meiner PN an dich angesprochen). Dafür muss ich mich aber für die Initialisierung und Fnialisierung der gesamten Elemente kümmern, dereferenziere ich eines der Elemente ohne dies vorher zu tun, kriege ich im besten fall eine EAccessViolation um die Ohren geworfen, das passiert bei einem array of TSomeType nicht.

jbg 6. Nov 2005 17:09

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von tommie-lie
Dafür muss ich mich aber für die Initialisierung und Fnialisierung der gesamten Elemente kümmern

Und dafür benutzt man dann New bzw. Dispose, wenn man nicht aus ganz bestimmten Gründen das Initialize bzw. Finalize umgehen möchte.

Nogge 6. Nov 2005 17:27

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
@jbg: Jep, das ist ja auch klar. Ich gebe ja durch SetLength() nur den Speicher für die Pointer frei, nicht aber den Speicherbereich, den der record einnimmt.

@marabu: Es handelte sich hier um ein Missverständnis. Ich dachte anfangs, SetLength() "weiß" bereits VOR der der Zuweisung der einzelnen string-Variablen, dass diese mit 6 Bytes Inhalt (="Name-3") + 1 Byte string-Zeiger + Byte Integer-Wert aus dem record initialisiert werden.
Meine völlig falsche Selbsterklärung, wie diese 8 Bytes zustande kommen, gehört nun der Vergangenheit an und ich weiß es jetzt besser. Vielen Dank an alle, die meine Verwirrungen beseitigen und mir beim Erweitern der Grundkenntnisse helfen konnten!

Bis zum nächsten Problem, Nogge :wink:

tommie-lie 6. Nov 2005 17:42

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Zitat:

Zitat von Nogge
Ich dachte anfangs, SetLength() "weiß" bereits VOR der der Zuweisung der einzelnen string-Variablen, dass diese mit 6 Bytes Inhalt (="Name-3") + 1 Byte string-Zeiger + Byte Integer-Wert aus dem record initialisiert werden.

Dein Schema verstehe ich zwar nicht ganz (ein Integer hat 4 Byte, nicht 1), aber nein, die 3*8 Byte rühren von drei Elementen zu je 8 Byte, weil das Record (sizeof(TItem)) 8 Byte groß ist: 4 Byte für den Integer und 4 Byte für den String, der im Array nur ein Pointer ist, also die gleiche Größe Besitzt wie ein Pointer (sizeof(Pointer) = sizeof(string)). Der Pointer zeigt auf das erste Zeichen im String, sämtliche String-Operationen sind somit Compiler-Magic. Wenn ich mich recht erinnere ist das aber nicht, wie Flocke sagte, Teil der RTTI, sondern wird bereits zur Compile-Time vollkommen ohne Aufbau irgendwelcher Tabellen im Speicher entschieden, da die Größe des Records mit der Typendeklaration schon festliegt.


Zitat:

Zitat von jbg
Zitat:

Zitat von tommie-lie
Dafür muss ich mich aber für die Initialisierung und Fnialisierung der gesamten Elemente kümmern

Und dafür benutzt man dann New bzw. Dispose, wenn man nicht aus ganz bestimmten Gründen das Initialize bzw. Finalize umgehen möchte.

Demnach sind New() und Dispose() nur GetMem() und FreeMem() mit implizitem Initialize() und Finalize()? Sorry für die blöde Frage, aber ich habe Delphi immer noch nicht in der VM installiert und in meinem Kopf finden sich gerade keine Erinnerungen dazu (was auch daran liegen mag, daß ich selten mit Records gearbeitet habe, die dynamische Typen enthielten :mrgreen:)...

jbg 6. Nov 2005 23:02

Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
 
Ja.
Delphi-Quellcode:
function New(Size: Longint; TypeInfo: Pointer): Pointer;
begin
  GetMem(Result, Size);
  if Result <> nil then
    Initialize(Result, TypeInfo);
end;

procedure Dispose(P: Pointer; TypeInfo: Pointer);
begin
  Finalize(P, TypeInfo);
  FreeMem(P);
end;


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