AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi SetLength(dyn. array, 0) vs. Finalize() vs. nil
Thema durchsuchen
Ansicht
Themen-Optionen

SetLength(dyn. array, 0) vs. Finalize() vs. nil

Ein Thema von Nogge · begonnen am 4. Nov 2005 · letzter Beitrag vom 7. Nov 2005
Antwort Antwort
Seite 2 von 2     12   
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#11

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

  Alt 6. Nov 2005, 10:57
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.
  Mit Zitat antworten Zitat
Nogge

Registriert seit: 15. Jul 2004
336 Beiträge
 
Delphi 7 Professional
 
#12

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

  Alt 6. Nov 2005, 11:18
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...
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#13

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

  Alt 6. Nov 2005, 11:33
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.
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#14

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

  Alt 6. Nov 2005, 15:14
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 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 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 von marabu:
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).
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#15

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

  Alt 6. Nov 2005, 15:57
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 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.
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#16

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

  Alt 6. Nov 2005, 18:09
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.
  Mit Zitat antworten Zitat
Nogge

Registriert seit: 15. Jul 2004
336 Beiträge
 
Delphi 7 Professional
 
#17

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

  Alt 6. Nov 2005, 18:27
@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
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#18

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

  Alt 6. Nov 2005, 18:42
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 von jbg:
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 )...
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#19

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

  Alt 7. Nov 2005, 00:02
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;
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:05 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