![]() |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Zitat:
Folgerichtig wäre der einzig wahre Beitrag, bei dem Du nichts zu bemängeln hättest, dieser hier: "Ja. Ja." Zitat:
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
Danke himitsu und Thom! Das hilft mir weiter.
@Stevie Danke für's Nachschauen. Dennoch macht für mich gerade der Ton die Musik. Ein "Ist schon lange bekannt" beinhaltet im Unterton ein "Ach - und dir nicht!? Wohl keine Ahnung von der Thematik?". Auf eine sachlich gestellte Frage erwarte ich auch eine sachliche Antwort. Die meisten hier im Forum können das. Im Gegensatz dazu klingt nahezu jede Antwort von Dir überheblich. Schade - bei Deinem Wissen hättest Du das eigentlich nicht nötig. Zum Thema "Workarounds"
Beide Einträge betreffen übrigens "Version: 14.0". Dumme Frage: Gab's zu diesem Zeitpunkt schon anonyme Methoden? Zitat:
Sorry - aber das ist einfach dumm und keine sachliche Antwort wert. Zitat:
Stevie's Post brachten - außer mehreren Belehrungen - keinen Beitrag zur Lösung des Problems. Wozu also das Ganze? Das es ganz anders geht, beweisen die Beiträge von Sebastian, himitsu und Thom. Nochmals vielen Dank an die drei! :thumb: Damit beende ich die Off-Topic-Diskussion meinerseits. Wer noch Bemerkungen dazu hat - bitte per PM. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Edit: egal...
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
Zitat:
Zitat:
Zitat:
Überheblich könnte übrigens auch der sein, der frisch in einem Forum ist und gleich rumkoffert. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Ja, manche Mitglieder sind manchmal etwas unhöflich oder streitlustig.
Wenn du Stevies ersten Betrag anstößig findest solltest du dir aber ein dickeres Fell zulegen. Durch solche Reaktionen wie von dir eskalieren solche Situationen häufig und damit geht dir eine Menge Antworten, vernünftiger Diskussion und letztlich Wissen verloren. Und: die Links zu den QC-Einträgen sind wertvolle Informationen und wenn nicht dir, dann helfen sie vielleicht später jemand anderem der diesen Thread liest. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Sehe ich genau so. Und nu' kommt mal wieder auf den Boden der Tatsachen zurück. Vor dem nächsten Posting einfach dreimal durchatmen und sich fragen, ob das die Sache wirklich wert ist.
|
AW: Speicherleck bei der Verwendung von anonymen Methoden
Zurück zum Thema. Soweit ich mich entsinnen kann, reicht es aus, wenn die Referenz der anonymen Methode explizit auf nil gesetzt wird.
Also in deinem Fall irgendwo im Destruktor:
Delphi-Quellcode:
FProc := nil;
Und der Leak dürfte verschwinden. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Zitat:
Zusätzlich zu den in den QC Einträgen wäre der simpelste Testcase, der mir gerade einfällt, folgender:
Delphi-Quellcode:
program Test;
{$APPTYPE CONSOLE} uses SysUtils; type TTest = class private FProc: TProc; public constructor Create; end; constructor TTest.Create; var Proc: TProc; begin Proc := procedure begin end; FProc := procedure begin end; end; begin ReportMemoryLeaksOnShutdown := True; TTest.Create.Free; end. |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Noch eine Merkwürdigkeit im Zusammenhang mit anonymen Methoden:
Eine anonyme Methode ist nach außen hin nur ein einfacher Pointer. Ein SizeOf(TProc) liefert also unter 32 Bit erwartungsgemäß 4 Byte. Im Gegensatz dazu bestehen Objekt-Methoden aus einem Daten- und einem Code-Pointer. Deshalb liefert SizeOf(TMethod)=8 (unter 32 Bit). Jetzt sollte man natürlich annehmen, daß der doppelt so große Wert von TMethod nicht zuweisungskompatibel zum "kleineren" TProc ist. Entgegen jeder Logik funktioniert das aber doch: Der Compiler generiert bei einer derartigen Zuweisung einfach eine anonyme Methode und bindet die Variable Self, die zu der Objekt-Methode gehört. Ich finde dieses Verhalten genial, da damit Ereignishandler wahlweise Objekt- oder anonyme Methoden sein können. Ein kleines Beispiel:
Delphi-Quellcode:
type
TNotifyProc = TProc<TObject>; //anstelle von TNotifyEvent TMyObject = class private FValue: Integer; FOnChange: TNotifyProc; procedure SetValue(Value: Integer); public property Value: Integer read FValue write SetValue; property OnChange: TNotifyProc read FOnChange write FOnChange; end; TForm1 = class(TForm) [...] private procedure MyObjectChange(Sender: TObject); end; procedure TMyObject.SetValue(Value: Integer); begin if FValue<>Value then begin FValue:=Value; if assigned(FOnChange) then FOnChange(Self); end; end; procedure TForm1.Button1Click(Sender: TObject); var MyObject: TMyObject; begin MyObject:=TMyObject.Create; try MyObject.OnChange:=MyObjectChange; MyObject.Value:=1; MyObject.OnChange:=procedure(Sender: TObject) begin ShowMessage(IntToStr(TMyObject(Sender).Value)); end; MyObject.Value:=2; finally MyObject.Free; end; end; procedure TForm1.MyObjectChange(Sender: TObject); begin ShowMessage(IntToStr(TMyObject(Sender).Value)); end; |
AW: Speicherleck bei der Verwendung von anonymen Methoden
Referenzen bestehen intern aus einem geheimgehalten Interface.
Und ein Interfacezeiger ist nunmal auch nur ein Pointer. Schade eigentlich, denn durch die Geheimhaltung und mangels entsprechender öffentlicher Methoden kann man Referenzen dadurch nicht vergleichen, bzw. prüfen was sich darin befindet. Wobei die Referenzen keine Methoden als anonyme Methoden "binden", sondern sie können einfachen alles "aufnehmen" ... vermutlich besitzen sie intern Speicher (eventuell überladen) und eine Typ-Variable, welche die Art des aufgenomenen "Zeigers" angibt. Bei einem Aufruf wird dann einfach der entsprechende Typ ausgewertet und aufgerufen.
Delphi-Quellcode:
.
property OnChange: TNotifyProc read FOnChange write FOnChange;
Hierfür wollte ich mir mal eine TList<> erstellen, welche mehrere Events verwalten kann, aber leider war es mir nicht mehr möglich einmal registrierte Events "geziehlt" wieder aus der Liste zu entfernen. :cry: PS: Im Zusammenhang mit anonymen Methoden, nimmt diese Referenz auch noch ganze Sätze von geshareten Variablenzeigern mit in sich auf.
Delphi-Quellcode:
MyObject.OnChange:=procedure(MySender: TObject)
begin ShowMessage(MySender.ClassName + ' ' + IntToStr(TMyObject(MySender).Value) + ' ' + Sender.ClassName); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:19 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