Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   record fillchar Speicherleck (https://www.delphipraxis.net/180020-record-fillchar-speicherleck.html)

baumina 17. Apr 2014 08:09

record fillchar Speicherleck
 
Speicherverwaltung war noch nie meine Stärke. Wie vermeide ich sinnvoll folgendes Speicherleck?

Delphi-Quellcode:
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.
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.

Bernhard Geyer 17. Apr 2014 08:14

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:
GlobVar.S1 := ''
GlobVar.S2 := ''
machen

Nersgatt 17. Apr 2014 08:21

AW: record fillchar Speicherleck
 
Ich würde dem Record dann eine Procedure verpassen, um ihn zu leeren:

Delphi-Quellcode:
MyRecord = record
    S1 : String;
    S2 : String;
    procedure Clear;
  end;
Somit könntest Du dann irgendwo einfach GlobVar.Clear aufrufen.

baumina 17. Apr 2014 08:32

AW: record fillchar Speicherleck
 
Klasse, danke Euch beiden!!!!

Stevie 17. Apr 2014 08:39

AW: record fillchar Speicherleck
 
Oder
Delphi-Quellcode:
GlobVar := Default(MyRecord);
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).
Anders sähe es natürlich bei einer lokalen Variable aus!

baumina 17. Apr 2014 09:03

AW: record fillchar Speicherleck
 
Delphi-Quellcode:
Default
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:

himitsu 17. Apr 2014 09:05

AW: record fillchar Speicherleck
 
Und Delphi-Referenz durchsuchenFinalize da, wo es
Delphi-Quellcode:
Default(...)
noch nicht gab.

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.

p80286 17. Apr 2014 10:00

AW: record fillchar Speicherleck
 
Zitat:

Zitat von himitsu (Beitrag 1255953)
Und Delphi-Referenz durchsuchenFinalize da, wo es
Delphi-Quellcode:
Default(...)
noch nicht gab.

Gute Idee. Aber, ich hab gerade in der Hilfe gestöbert, was ist mit solchen Records:
Delphi-Quellcode:
record
  Name : string;
  Vorname : string;
  Geburtstag : tdatetime;
  Kenner : array [0..8] of char;
  GenommeneUrlaubstage : byte;
end;
werden Geburtstag,Kenner und GenommeneUrlaubstage genullt oder nicht?

Gruß
K-H

himitsu 17. Apr 2014 11:57

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.

Stevie 17. Apr 2014 13:14

AW: record fillchar Speicherleck
 
Zitat:

Zitat von p80286 (Beitrag 1255973)
Gute Idee. Aber, ich hab gerade in der Hilfe gestöbert, was ist mit solchen Records:
Delphi-Quellcode:
record
  Name : string;
  Vorname : string;
  Geburtstag : tdatetime;
  Kenner : array [0..8] of char;
  GenommeneUrlaubstage : byte;
end;
werden Geburtstag,Kenner und GenommeneUrlaubstage genullt oder nicht?

Ja, Default macht nix anderes, als zusätzlich noch FinalizeRecord aufzurufen, wenn managed Fields vorhanden sind.

Hier mal der Auszug aus dem assembler code:
Code:
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
Die Funktion gibts seit Generics, damit man in generischem Code ein leeres Element von irgendeinem Typ erzeugen kann (Default(T)).
Lässt sich aber ebend auch prima in nicht generischem Code benutzen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:59 Uhr.
Seite 1 von 2  1 2      

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