![]() |
Dynamische Packages - Forms anzeigen - Leak
Ich möchte gerne forms in packages zur Verfügung stellen und diese dynamisch laden.
Jetzt habe ich festgestellt, dass der Speicher nicht mehr freigegeben wird (also auch bei leeren Forms ohne Nutzer-Interaktion oder Komponenten). Wenn die Form angzeigt wird, werden ca. 300 byte nicht mehr freigegeben (vorausgesetzt, "memoryused" stimmt) Was dagegen tun? BPL mit Form:
Delphi-Quellcode:
Hauptprgramm:
Unit Gui.LoaderTestform;
{ This is a Test form for loader to test for memory leaks } Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; Type TTestform = Class(TForm) Private { Private declarations } Public { Public declarations } End; Var Testform: TTestform; Implementation {$R *.dfm} Initialization Registerclass(TTestform); Finalization Unregisterclass(TTestform); End. Form anzeigen, nachdem das Package dynamisch geladen wurde:
Delphi-Quellcode:
Den leak teste ich über die Differenz zweier Aufrufe folgender Funktion:
Function Tplgfrm.Loadform(Parent: Tcomponent; Form: String; Modal: Boolean)
: Boolean; Var FormClass: Tformclass; Begin Result := True; Try Form := 'T' + Form; FormClass := TFormClass(GetClass(Form)); If FormClass = Nil Then Begin Raise Exception.Create('The form "' + Form + '" is not available.'); Result := Not Result; End Else Begin With TComponentClass(FormClass).Create(Parent) As TCustomForm Do Try If Modal Then Showmodal Else Show; Finally // Free; End; End; Except Raise Exception.Create('Form could not be loaded.'); Result := Not Result; End; End;
Delphi-Quellcode:
Function MemoryUsed: Cardinal;
Var St: TMemoryManagerState; Sb: TSmallBlockTypeState; Begin GetMemoryManagerState(St); Result := St.TotalAllocatedMediumBlockSize + St.TotalAllocatedLargeBlockSize; For Sb In St.SmallBlockTypeStates Do Begin Result := Result + Sb.UseableBlockSize * Sb.AllocatedBlockCount; End; End; |
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
nach mehmaligen Aufrufen weiß keiner mehr, was Result nun ist. |
AW: Dynamische Packages - Forms anzeigen - Leak
Result wurde am anfang auf false gesetzt.
Wenn die form erfolgreich geladen wird, soll der Rückgabewert ja "true" sein. Die form soll ja meist nur einmal geladen werden (und modal angezeigt). OK, ich seh grad: Result müsste am Anfang auf True initialisiert werden,um sinn zu machen. Zitat:
|
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
|
AW: Dynamische Packages - Forms anzeigen - Leak
NOT als "Funktion" sieht irgendwie immer krank aus.
NOT ist ein Operator. (die Klammer gehrt nicht zum NOT) Delphi hält keine Informationen welche Form Komponente oder anderer Speicher im Code eines bestimmten Moduls (EXE, DLL, BPL) erstellt/reserviert wurde und somit kann Delphi auch nichts automatisch freigeben, wenn du ein Modul wieder entlädst. Fazit: DU mußt dir das merken und es beim Entladen der BPL das dann selber freigeben. (wichtig vorallem bei Komponenten, die im Betrieb Code aus diesem Modul verwenden) |
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
Zitat:
Delphi-Quellcode:
Oder muss ich jede einzelne Komponente auf der Form zerstören? (Das Problem tritt ja auch bei einer komplett leeren Form auf)
With TComponentClass(FormClass).Create(Nil) As TCustomForm Do
Try If Modal Then Showmodal Else Show; Finally Free; //hier? End; |
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
Delphi-Quellcode:
, was theoretisch den Wert Result umkehren könnte, steht immer hinter dem Werfen einer Exception und wird von daher im realen Leben vermutlich nie ausgeführt. (oder hab' ich da was übersehen?)
Result := Not(Result)
Dashier verstehe ich nicht:
Delphi-Quellcode:
Du erstellst ein Formular, dann entscheidest Du, ob es Modal oder nicht angezeigt werden soll.
With TComponentClass(FormClass).Create(Nil) As TCustomForm Do
Try If Modal Then Showmodal Else Show; Finally Free; End; Bei ShowModal dürfte das auch funktionieren, wenn im Finally das Free aufgerufen wird. Wie ist das denn beim Show? Bleibt das Programm da quasi im Quelltext stehen und wartet, bis das Formular geschlossen wird, bevor im Finally das Free aufgerufen wird? Hab's gerade mal unter Delphi 7 ausprobiert: Das auf diese Art und Weise erstellte Formular bekomme ich nicht wirklich zu sehen, ein kurzes Flimmern, bei dem man erahnen kann, dass da irgendwo ein Formular angezeigt werden könnte, ja, aber ein benutztbares Formular? Fehlanzeige. Automatisch "zerstört" werden könnte es nur, wenn im Create statt Nil ein Parent angegeben wird. Wenn niemand weiß, wem das Formular gehört, wer soll denn dann wissen, wann es "beseitigt" werden soll? |
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
Das Formular könnte theoretisch von unterschiedlichen Anwendungen (oder anderen Formularen) geladen werden. Habe daher jetzt einen "parent" parameter eingefügt, der dann für die Freigabe zuständig sein muss und dem ich als Result die erstellte form zur verfügung stelle:
Delphi-Quellcode:
Function Tplgfrm.Loadform(Parent: Tcomponent; Form: String; Modal: Boolean)
: TCustomForm; Var FormClass: Tformclass; Begin Try Form := 'T' + Form; FormClass := TFormClass(GetClass(Form)); If FormClass = Nil Then Raise Exception.Create('The form "' + Form + '" is not available.') Else Begin Result := TComponentClass(FormClass).Create(Parent) As TCustomForm; With Result Do Try If Modal Then Showmodal Else Show; Finally // Free; End; End; Except Raise Exception.Create('Form could not be loaded.'); End; End; //Aufruf Form := Loadform(Application, 'Formname', True); Form.Free; |
AW: Dynamische Packages - Forms anzeigen - Leak
Ich versuchs mal naiv:
Du hast da Deine FormClass. Wie wäre es, wenn Du die Funktion von diesem Typ machst? Sowas in der Art:
Delphi-Quellcode:
Im Programm wäre dann eventuell sowas möglich:
Function Tplgfrm.Loadform(Parent: Tcomponent; Form: String; Modal: Boolean) : Tformclass;
Begin Try Form := 'T' + Form; Result := TFormClass(GetClass(Form)); If not Assigned(Result) Then Begin Raise Exception.Create('The form "' + Form + '" is not available.'); End Else Begin With TComponentClass(Result).Create(Parent) As TCustomForm Do Try If Modal Then Showmodal Else Show; Finally // Free; End; End; Except Raise Exception.Create('Form could not be loaded.'); End; End;
Delphi-Quellcode:
Wobei, das Anzeigen des Formulares würd' ich aus der Funktion rausnehmen und im aufrufenden Programm machen, dann kannst Du besser entscheiden, ob das Formular direkt nach dem ShowModal freigegeben wird oder nicht.
Procedure irgendwas;
Var FormClass : TFormClass; begin FormClass := plgfrm.Loadform(Self,'FromWieAuchImmer', True); if Assigned(FormClass) then begin ... FormClass.Close; FormClass.Free; end; end; Bei 'nem Show kannst Du die Freigabe dann auch beim Beenden des Programmes machen (oder an anderer, sinnvoller Stelle), die variabel FormClass muss dann nur an entsprechender Stelle deklariert werden und nicht innerhalb der Prozedur, die das Formular "anfordert". |
AW: Dynamische Packages - Forms anzeigen - Leak
Übrigens verringert sich das Leak bei Weglassen von Registerclass in der Unit der einzelnen Forms. (Natürlich ist das notwendig um die Klassen zu identifizieren, wenn ich dynamische Packages nutze). Irgendein Workaround / Tip hierfür?
|
AW: Dynamische Packages - Forms anzeigen - Leak
Das mit dem ausgelagerten Anzeigen ist eine gute Idee.
Danke. Hilft allerdings noch nicht gegen das problem, dass non-modale Forms nicht korrekt angezeigt werden. Und das eigentliche Problem, dass durch die Klassenregistration Speicher geleakt zu werden scheint.
Delphi-Quellcode:
Initialization
Registerclass(TTestform); // hier Finalization Unregisterclass(TTestform); Zitat:
|
AW: Dynamische Packages - Forms anzeigen - Leak
Das mit dem RegisterClass ist seltsam. Wie hast du deine Methode denn getestet wenn das Formular gar nicht registriert ist?
Aber mach mal im OnClose von deiner BPL Form
Delphi-Quellcode:
rein. Dann wird das Form beim Schließen freigegeben und das mit dem Leak sollte sich erledigt haben.
Action := caFree;
|
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
wird ja hier
Delphi-Quellcode:
auch an entsprechender Stelle abgebrochen.
Form := Loadform(Application, 'Testform', True);
If Form <> Nil Then With Form Do Begin Showmodal; // Leaks 176 bytes Free; End; Da es sich bei einer Testform um ein komplett leeres (neu erstelltes) Formular ohne jeglichen code handelt, das nichts ausführt und keine komponenten hat, außer der Form selbst, dachte ich dass es nur an der Registierung hängen kann...Denkfehler? Anmerkungen: - Auch wenn ich bei bestehender Registrierung den gesamten Teil (..Loadform...) auslasse (i.e check ob loadform NIL ergibt) und die Form nicht lade, gibts ein Leck. - Wenn die Form mehrmals nacheinander aufgerufen und wieder geschlossen wird, bleibt die Leckgröße konstant Die Action:=cafree festzulegen, hat leider keinen Effekt gezeigt. |
AW: Dynamische Packages - Forms anzeigen - Leak
Und wieviel "Leak" wird es, wenn du die Form 100 Mal anzeigen lässt?
|
AW: Dynamische Packages - Forms anzeigen - Leak
Zitat:
|
AW: Dynamische Packages - Forms anzeigen - Leak
Gibts nicht ein bekanntes (noch nicht behobener) Leak beim Dynamischen Laden und Endladen von Packages?
ist also (wenn man nicht selbst Quellcode anpassen kann als "As Designed" anzusehen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:55 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