![]() |
GetMem / FreeMem - New / Dispose
Hallo zusammen,
ich weiß, dass GetMem und FreeMem sowie New und Dispose zusammen gehören. Mal ne "dumme" Frage, was würde passieren, wenn ich mit New Speicher reserviere und mit FreeMem diesen freigeben würde? Gruß Alex |
AW: GetMem / FreeMem - New / Dispose
Grundsätzlich erstmal nichts, aber New und Dispose beachten die RTTI.
z.B. wenn du einen Record in dem "Pointer hat, welcher z.B. "lange" Strings enthält, dann würde Dispose diesen String freigeben, während FreeMem das nicht macht. Also besser immer nur die zusammengehörigen Funktionen zusammen benutzen. New = GetMem + Initialize/InitializeRecord Dispose = Finallize/FinallizeRecord + FreeMem Tipp: Schau doch einfach mal in deine System.pas rein. :zwinker: |
AW: GetMem / FreeMem - New / Dispose
Ok danke.
Das heißt, wenn ich folgenden Record habe, würde FreeMem den String nicht richtig freigeben?
Delphi-Quellcode:
Gruß
TData = packed record
a: LongWord; b: String[40]; c: TDateTime; end; Alex |
AW: GetMem / FreeMem - New / Dispose
Wo ist da der LANGE String?
|
AW: GetMem / FreeMem - New / Dispose
Nein, den würde es freigeben.
DAS ist ein "kurzer" String. :angle2: String[123] = ![]() String = ![]() ![]() WideString = WideString, was ein OLE-Wrapper um ![]() |
AW: GetMem / FreeMem - New / Dispose
Ok, wusste nicht genau, was du mit "lange" Strings meinst :-)
Also würde bei New und FreeMem (mit richtiger Größenangabe) eigentlich nichts passieren bei dem geposteten Record? Gruß Alex |
AW: GetMem / FreeMem - New / Dispose
Ich würde es etwas anders formulieren:
Benutze nur New/Dispose, es sei denn es ist nicht zu umgehen und Du weißt was Du tust, dann benutze Getmem/Freemem. Die andere Ausnahme ist, wenn Du Wert auf vollkommen unerklärlich Fehler legst, da ist Getmem/Freemem wunderbar für geeignet. Gruß K-H |
AW: GetMem / FreeMem - New / Dispose
Jupp.
FreeMem neigt eventuell zu Speicherlecks, da ja nur der Pointer selber freigegeben wird, aber nichts, was darin eventuell verlinkt wurde. Und auf GetMem folgen eventuell unerklärliche gemeine und eigentlich erklärliche Fehler, wenn gewisse Dinge nicht ordnungsgemäß initialisiert wurden. |
AW: GetMem / FreeMem - New / Dispose
Zitat:
Gruß Alex |
AW: GetMem / FreeMem - New / Dispose
"lange" Stringvariablen, Interfaces, Variants und dynamische Arrays müssen initialisiert sein, sonst knallt die automatische Speicherverwaltung.
|
AW: GetMem / FreeMem - New / Dispose
Zitat:
Delphi-Quellcode:
Das sind 84 Byte Du arbeitest also mit Getmem(p,84);
type
MyRec = record f1 : Byte; f2 : Word; f3 : String[80] end; Das Dumme ist nur, das ein mögliches Alignment nicht beachtet wurde. Und immer wenn der String 80..75 Zeichen lang wird, dann trittst Du irgend einer anderen Variablen auf die Füße. Oder Du hast ein altes 16Bit-Programm und es wird in einer 32-Bit Umgebung neu erstellt. Dann ist ein Integer nicht mehr 16 sondern 32 Bit groß. Und zur Ermittlung des Speicherplatzes wird nicht Sizeof verwendet, sondern fest kodierte Werte. Das kann u.U. recht eklig werden. Gruß K-H |
AW: GetMem / FreeMem - New / Dispose
Er meint dass wie folgt:
Delphi-Quellcode:
Du musst halt sozusagen die hierarchie deines Pointers, wenn du es so machst wie in dem Beispiel, von unten nach oben freigeben, erst die untengeordneten, danach die oberen.
type
TRecord1 = record Wert1 : Integer; end; PRecord1 = ^TRecord1;//Pointer auf die Daten des TRecord1. TRecord2 = record Record1 : PRecord1; //Eine Variable vom PRecord1 end; PRecord2 = ^TRecord2; //Wenn du dies nun wie folgt initalisiertst: var Record2 : PRecord2; begin GetMem(Record2,SizeOf(TRecord2)); //Speicher vom Record-Typ, nicht vom Pointer-Typ :-D GetMem(Record2.Record1,SizeOf(TRecord1)); //Den TRecord1-Pointer in TRecord2 initalisieren. Record2.Record1.Wert1 := 10; //Als Test //Wenn du dies nun wie folgt freigibst nur... FreeMem(Record2,SizeOf(TRecord2)); //Zur Sicherheit würd ich die Größe nochmal übergeben. //...bleibt der Pointer auf TRecord1 in TRecord2 enthalten, also der Speicher von TRecord1 wird nicht freigegeben. Weil in TRecord1 nur der Pointer(Adresse, wo TRecord1 seine Daten hat), also nur der Adresswert, freigegeben wird. //In diesem Fall müsste mal folgendes machen: FreeMem(Record2.Record1,SizeOf(TRecord1));//Alle in diesem Pointer-Record-Typ enthaltenen Pointer musst du selbst freigeben. Bei Klassen halt Free davor aufrufen. FreeMem(Record2,SizeOf(TRecord2));//Danach erst den "Oben"-Pointer freigeben. end; Auserdem macht GetMem nur Platz für die Daten. Es ist meist so, dass dort Werte von anderen freigegeben Speichern noch liegt. Weil GetMem halt nur sagt, so hier kannst deine Daten reinschreiben. Es gibt aber auch noch die AllocMem, mit der dann der Speicher mit "0"Bytes aufgefühlt wird, um solche Fehler zuvermeiden. Das kann dan auch mit FreeMem freigegen werden. Dies ist genauso als würdest du GetMem und danach FillChar aufrufen. EDIT: Habe gerade was getestet. Bei New/Dispose werden Pointer initalisiert, die nach Dispose noch verfügbar sind. D.h. der Speicher wird von Delphi freigegeben. Sozusagen wenn du wirklich Kontrolle über den Speicher für solche Pointer haben willst verwende lieber, GetMem/FreeMem. Bei falscher verwendung können halt solche genannten Fehler entstehen. Hoffe ich konnte es dir erklären. Ist ein wenig kompliziert am anfang, ging mir auch so :-D. Aber einmal kapiert, sind Pointer und Speicher erstellen/freigeben ein kinderspiel xD |
AW: GetMem / FreeMem - New / Dispose
Zitat:
Wie meinst du das mit den "String 80..75 Zeichen", dass ich dann einer anderen Variablen auf die Füße trete? Gruß Alex |
AW: GetMem / FreeMem - New / Dispose
Zitat:
Zitat:
Sobald der String länger als 74 Byte wird landen Zeichen im nicht zu Deinem Record gehörenden Speicher. Und das kann alles mögliche oder aber auch nichts sein. D.H. der Fehler wird unter Umständen erst auf einem anderen Rechner oder einem anderen Benutzer erkannt. Gruß K-H |
AW: GetMem / FreeMem - New / Dispose
Zitat:
New und Dispose holen sich die "richtige" Größe aus der RTTI und führen auch noch eventuell notwendige Initialisierungen/Finalisierungen durch. |
AW: GetMem / FreeMem - New / Dispose
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 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 by Thomas Breitkreuz