![]() |
Delphi-Version: XE
Speicherleck bei der Verwendung von anonymen Methoden
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!
Folgendes Problem: Bei der Verwendung dieses Quelltextes entsteht ein Speicherleck:
Delphi-Quellcode:
Anhang 35373
type
TForm1 = class(TForm) Memo1: TMemo; Panel1: TPanel; Button1: TButton; Edit1: TEdit; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); private FProc: TProc; public { Public-Deklarationen } end; procedure TForm1.FormCreate(Sender: TObject); var Func: TFunc<String>; begin ReportMemoryLeaksOnShutdown:=true; Func:= function: String begin Result:=Edit1.Text; end; Memo1.Lines.Add(Func); FProc:= procedure begin Memo1.Lines.Add(Func); end; end; procedure TForm1.Button1Click(Sender: TObject); begin FProc; end; Momentan kann ich leider nicht überprüfen, ob das auch bei XE2 auftritt (meine Testversion ist gerade abgelaufen). Gibt es eine Möglichkeit, dieses Speicherleck zu verhindern? |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Umgehen lässt sich das Problem leicht:
Mach aus Func auch ein privates Feld statt einer lokalen Variable. Schöner ist aber wohl diese Lösung:
Delphi-Quellcode:
procedure TForm142.FormCreate(Sender: TObject);
procedure DoInit(Func: TFunc<String>); begin Memo1.Lines.Add(Func); FProc := procedure begin Memo1.Lines.Add(Func); end; end; begin ReportMemoryLeaksOnShutdown := true; DoInit(function: String begin Result := Edit1.Text; end); end; |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Da wird wohl die eingebetette Reference nicht mehr freigegeben.
Am Generic liegt es nicht, dann wenn man
Delphi-Quellcode:
durch einen richtigen Typen ersetzt, ändert sich nichts.
TFunc<String>
Lösungen: - im QC melden und hoffen es wird eventuell irgendwann in den nächsten Jahrzehnten behoben - auf verschachtelte Referencen verzichten - oder Func ebenfalls als privates FFunc in der Form speichern [add] wie schonmal genannt - diesen Fehler einfach ignorieren (wird ja eh nie behoben) - schmutzige Tricks, um diesen Fehler provisiorisch zu umgehn *1 1)
Delphi-Quellcode:
als letzen Befehl in FormCreate,
IInterface(PPointer(@Func)^)._Release;
aber sollte dieser Fehler wirklich mal irgendwann behoben werden, dann raucht dir die Anwendung ab. :stupid: |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Gerade getestet: Das Problem tritt auch bei XE2 noch auf.
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
Tritt das Speicherleck bei jeder verwendung auf oder einmalig beim ersten Aufruf?
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
Einmal, es wird ja schließlich die Funktion nicht freigegeben und die existiert nun einmal nur einmal...
// EDIT: Bzw. wenn man den Code aus FormCreate mehrfach ausführt, wird natürlich bei jeder Ausführung ein Speicherleck produziert. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
@jaenicke
Vielen Dank für's Testen und die nette Antwort! Zitat:
Ich hatte nicht gefragt, ob das Problem bekannt ist, sondern
Ohne einen überheblichen Ton kannst du wohl überhaupt nichts von dir geben? :wall: |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Zitat:
Da der Eintrag nicht geclosed ist, tritt der Bug noch in XE2 auf (1.) Wenn du dir die Einträge anschaust, siehst du woran das Problem liegt und auch Workarounds (2.) Im übrigen wurde hier in diesem Thread darauf hingewiesen, einen QC Eintrag zu machen - daher habe ich mir die Mühe gemacht, das mal nachzuschauen. Wenn du Sachlichkeit mit Überheblichkeit verwechselst, tut's mir leid für dich. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
@carlo93
Zitat:
Zu Deiner Frage: Der Compiler speichert die von anonymen Methoden genutzen Variablen ( ![]() Aus für mich nicht ersichtlichen Gründen besitzen diese Frames nach der Erstellung der anonymen Methode einen RefCount-Wert von 2. Nach Beendigung der Methode (in Deinem Fall TForm1.Create) wird dieser Wert wieder um zwei verringert und das Frame-Objekt aus dem Speicher entfernt. Tritt jetzt der Fall ein, das die anonyme Methode in einer anderen weiterverwendet wird, erhöht der Compiler RefCount des Frame-Objektes um eins und es wird beim Aufräumen am Ende der Methode nicht mehr gelöscht. So weit - so gut. Dummerweise verringert der Compiler in diesem Fall RefCount nur um eins und somit bleibt das Frame-Objekt auch zum Schluß erhalten. Meiner Meinung nach ist das ein Fehler im Compiler. Da ich bei der Programmierung meines Frameworks auch auf dieses Problem gestoßen bin, habe ich dafür eine einfache Lösung entwickelt:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var Func: TFunc<String>; begin ReportMemoryLeaksOnShutdown:=true; Func:= function: String begin Result:=Edit1.Text; end; Memo1.Lines.Add(Func); FProc:= procedure begin Memo1.Lines.Add(Func); end; {$IF (CompilerVersion>=20) and (CompilerVersion<24)} //<- optimistisch ;-) if RefCount(Func)>2 //-> es existieren zusätzliche Referenzen then ReleaseMethod(Func); //<- RefCount wird um das fehlende Mal verringert {$IFEND} end; Zitat:
Delphi-Quellcode:
{$IF (CompilerVersion>=20) and (CompilerVersion<???)}
if IInterface(PPointer(@Func)^)._AddRef>3 then IInterface(PPointer(@Func)^)._Release; IInterface(PPointer(@Func)^)._Release; {$IFEND} |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:24 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