![]() |
record fillchar Speicherleck
Speicherverwaltung war noch nie meine Stärke. Wie vermeide ich sinnvoll folgendes Speicherleck?
Delphi-Quellcode:
Hintergrund : Ich hatte mich für einen globalen Record entschieden, da dieser alle wichtigen Daten meines aktuell gewählten Mantanten enthält, auf die ich ständig zugreifen muss. Fillchar deswegen, um bei einem Mandantenwechsel erst alle Inhalte zu leeren.
program Project2;
uses Forms; {$R *.res} type MyRecord = record S1 : String; S2 : String; end; var GlobVar : MyRecord; begin ReportMemoryLeaksOnShutdown := True; Application.Initialize; Application.MainFormOnTaskbar := True; fillchar(GlobVar, SizeOf(GlobVar), 0); Globvar.S1 := 'testString'; fillchar(GlobVar, SizeOf(GlobVar), 0); <-- ab jetzt Speicherleck Application.Run; end. |
AW: record fillchar Speicherleck
Mit Fillchar zerstörst du die Verwaltungsinformationen der Strings (Referenzzählung etc.) Also ganz böser Fehler!
Du solltest nur
Delphi-Quellcode:
machen
GlobVar.S1 := ''
GlobVar.S2 := '' |
AW: record fillchar Speicherleck
Ich würde dem Record dann eine Procedure verpassen, um ihn zu leeren:
Delphi-Quellcode:
Somit könntest Du dann irgendwo einfach GlobVar.Clear aufrufen.
MyRecord = record
S1 : String; S2 : String; procedure Clear; end; |
AW: record fillchar Speicherleck
Klasse, danke Euch beiden!!!!
|
AW: record fillchar Speicherleck
Oder
Delphi-Quellcode:
Abgesehen davon werden globale Variablen sowieso initialisiert, d.h. es besteht keine Veranlassung in deinem Beispiel, das von Hand zu tun (der Aufruf vor dem Zuweisen des strings).
GlobVar := Default(MyRecord);
Anders sähe es natürlich bei einer lokalen Variable aus! |
AW: record fillchar Speicherleck
Delphi-Quellcode:
Toller Befehl! Kenn ich nicht, finde auch keine Hilfe dazu, aber funktioniert, mal schauen ob ich mich daran in zwei Jahren noch erinnern kann. :thumb:
Default
|
AW: record fillchar Speicherleck
Und
![]()
Delphi-Quellcode:
noch nicht gab.
Default(...)
Aber das ganze in die Clear, Metode auszulagen kann nicht schaden. (wie dann darin geleert wird, ist egal, Hauptsache es wird "richtig" gemacht) FillChar setzt "blind" alles auf 0, wobei natürlich mutwillig die automatisch verwalteten Referenzen geschrottet werden. |
AW: record fillchar Speicherleck
Zitat:
Delphi-Quellcode:
werden Geburtstag,Kenner und GenommeneUrlaubstage genullt oder nicht?
record
Name : string; Vorname : string; Geburtstag : tdatetime; Kenner : array [0..8] of char; GenommeneUrlaubstage : byte; end; Gruß K-H |
AW: record fillchar Speicherleck
Kommt jetzt drauf an, wie es implementiert wurde.
Bei "Optimaler Laufzeigt" würden diese nicht behandelt, aber es spricht nichts dagegen nach dem Finalize nochmal ein FillChar/ZeroMemory drüber laufen zu lassen. (nil bleibt dann ja 0) Interfaces, dynamische Arrays (Kenner ist statisch), LongStrings (also AnsiString, WideString und UnicodeString) und Variants würde man sonst schrotten und Speicherlecks erschaffen. Wobei ShortString (und die Typen String[x]) aber ein statisches Array ist. |
AW: record fillchar Speicherleck
Zitat:
Hier mal der Auszug aus dem assembler code:
Code:
Die Funktion gibts seit Generics, damit man in generischem Code ein leeres Element von irgendeinem Typ erzeugen kann (Default(T)).
006494C5 8D45D0 lea eax,[ebp-$30]
006494C8 8B15E8936400 mov edx,[$006493e8] 006494CE E809EEDBFF call @FinalizeRecord 006494D3 8BF8 mov edi,eax 006494D5 33C0 xor eax,eax 006494D7 B90A000000 mov ecx,$0000000a 006494DC F3AB rep stosd Lässt sich aber ebend auch prima in nicht generischem Code benutzen. |
AW: record fillchar Speicherleck
Zitat:
Oder vielleicht brauchst du irgendwann eine Methode die Länderkennzeichen, Postleitzahl und Ort in einem String liefert. Warum also mit einem Record beginnen wenn doch eine Klasse einen Mehrwert bietet? Und du kannst mir glauben - irgendwann kommst du an den Punkt an dem du merkst dass du mehrere Mandanten-Objekte brauchst. Dann wirst du ärgern dass du an tausend Stellen auf einen globalen Record zugreifst. |
AW: record fillchar Speicherleck
[rethorische Frage]Wozu überhaupt noch Records?[/rethorische Frage]
|
AW: record fillchar Speicherleck
Records kann man in einem Zug in und aus einem Stream kopieren. (allerdings dürfen dann keine Pointer-Typen enthalten sein)
Records haben eine automatische Speicherverwaltung Man zieht nicht einen ganz so großen Schwanz an Vererbungs unr RTTI-Zeugs mit. Und man kann sowas wie die Operatoren nutzen, welches ohne eine automatische Speicherverwalung nunmal nicht geht. (nja, bei Interfaces und bei Objekten mit ARC ginge es dennoch, wenn/falls es implementiert ist und wenn die endlich mal den seit Jahren von mir gewünschen Copy-Operator implementieren) |
AW: record fillchar Speicherleck
Generell ist das Verwenden von globalen Variablen zu vermeiden, vor allem, weil es eine einfache Möglichkeit gibt, diese zu schützen.
Delphi-Quellcode:
Sinnvoll ist es auch den Record immutable (unveränderlich) zu gestalten und die Erzeugung des Wertes über einen Konstruktor zu regeln:
interface
function GlobValue : MyRecord; procedure SetGlobValue( const Value : MyRecord ); implementation var _GlobValue; function GlobValue : MyRecord; begin Result := _GlobValue; end; procedure SetGlobValue( const Value : MyRecord ); begin // prüfen, ob die Änderung erlaubt ist _GlobValue := Value; // Benachrichtigung über die Änderung end;
Delphi-Quellcode:
Im Konstruktor kann jetzt auf Plausibilität geprüft werden und bei unsinnigen Werten wirft man eine Exception.
MyRecord = record
private FS1 : string; FS2 : string; public constructor Create( const S1, S2 : string ); property S1 : string read FS1; property S2 : string read FS2; end; constructor MyRecord.Create( const S1, S2 : string ); begin // Validierung FS1 := S1; FS2 := S2; end; Mit diesen einfachen Mitteln wird es unmöglich gemacht, dass unbemerkt Änderungen gemacht werden oder inkonsistente Daten vorliegen. |
AW: record fillchar Speicherleck
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:15 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