![]() |
Delphi-Version: XE8
Seltsames Verhalten der Destruktoren
Hi zusammen
In meiner gegenwärtigen Testanwendung - SynpdfTestProject - tritt plötzlich ein seltsames verhalten der Destuktoren auf. Ich muss allerdings zugeben, ich hab das erst jetzt, bei Auftreten des Fehlers, gecheckt. Wenn ich die Anwendung beende, geschieht folgendes in der gezeigten Reiheenfolge:
Delphi-Quellcode:
WriteReportFile schreibt den Inhalt der Reportliste im eine Datei. Da diese das jeweilige Datum und die Zeit im Namen trägt, wird sie jedesmal neu angelegt, und es tritt eine Exception (im Debugmodus) auf.. Eine normale 'Fehlermeldung' die schell weggeklickt ist.
procedure TSynpdfMain.FormDestroy(Sender: TObject);
begin Self.WriteReportFile; FReportList.Free; end; Seit neuestem (heute) erhalte ich aber eine neue AV, und zwar hier:
Delphi-Quellcode:
Die einzige Änderung ist die Zeile mit der Freigabe der PDFPageClass, die ich vor Tagen schon hinzugefügt habe und die nie zu Problemen geführt hat. Ausgelöst wird der Fehler schon in der ersten Zeile bei
destructor TPDFiumFrame.Destroy;
begin _Document := 0; FPages.Free; PDFPageClass.Free; FReportList.Free; inherited; end;
Delphi-Quellcode:
_Document := 0;
Der Vollständigkeit halber hier auch noch die beiden Constructoren:
Delphi-Quellcode:
und
procedure TSynpdfMain.FormCreate(Sender: TObject);
begin FReportList := TStringlist.Create; FReportList.Sorted := False; FReportList.Add('________________________________________'); FReportList.Add('procedure TSynpdfMain.FormCreate;'); FReportList.Add('________________________________________'); end;
Delphi-Quellcode:
Weshalb jetzt plötzlich dieses Verhalten? In meiner Anwendung gibt es scon seit Wochen zwei Frameinstanzen, die jede vom Basisframe erbt und die beide von der Mainform zerstört wurden. Und damit auch ihr _Ducument - Handle (Das Handle des PDF-Dokumentes).
constructor TPDFiumFrame.Create(AOwner: TComponent);
begin {$IFDEF TRACK_EVENTS} AllocConsole; {$ENDIF} inherited; ControlStyle := ControlStyle + [csOpaque]; FZoom := 100; FPageIndex := -1; PDFPageClass := TPDFPageClass.Create; //<== meine zweite Änderung FSelBmp := TBitmap.Create; FSelBmp.Canvas.Brush.Color := RGB(50, 142, 254); FSelBmp.SetSize(100, 50); FPages := TList.Create; FReportList := TStringlist.Create; //<== meine erste Änderung FReportList.Sorted := False; FGetPageAt := 0; try FPDF_InitLibrary; except FStatus := TLabel.Create(Self); FStatus.Align := alClient; FStatus.Parent := Self; FStatus.Alignment := taCenter; FStatus.Layout := tlCenter; FStatus.Caption := sUnableToLoadPDFium; end; end; Gerade getestet und ebenso falsch:
Delphi-Quellcode:
Gruss
if _Document > 0 then
_Document := 0; Delbor |
AW: Seltsames Verhalten der Destruktoren
Wenn im Programmablauf TPDFiumFrame.Destroy vor TSynpdfMain.FormDestroy aufgerufen wird, existiert FReportList im FormDestroy nicht mehr und damit kann Self.WriteReportFile auch nicht mehr auf FReportList zugreifen, da ja bereits im TPDFiumFrame.Destroy freigegeben.
Ausserdem wird FReportList in TPDFiumFrame.Destroy und TSynpdfMain.FormDestroy freigegeben. Warum? |
AW: Seltsames Verhalten der Destruktoren
Form.OnDestroy wurde "früher" im Inherited des Destructor ausgeführt.
> Form.OldCreateOrder=True oder ganz alten Delphis Form.OnDestroy wird "aktuell" im BeforeDestruction ausgeführt. > Form.OldCreateOrder=False Beim Upgrade alter Formulare in neues Delphi steht dieses Property auf True. Bei neu erstellten Formularen im neuen Delphi steht dieses Property auf False. PS: Das Selbe gilt auch für OnCreate der Forms, also früher im Constructor und nun im AfterConstruction. Fazit: Stell OldCreateOrder auf False (sollte im XE8 schon lange drin sein) und pass auf die Aufrufreihenfolge der Events aus. > neu/aktuell : Create > OnCreate > ... > OnDestroy > Destroy > früher : Create > ... > Destroy - und da dann jeweils im Inherited das OnCreate und OnDestroy, also vor oder nach dem eigenem Code >> bei mir also fast immer OnCreate > Create > ... > Destroy > OnDestroy - da ich normalter Weise beim Erstellen das Inherited am Anfang und beim Freigeben am Ende stehen hab "Doppelt" freigeben ist kein Problem, wenn man es richtig macht. > ![]() Aber grundsätzlich sollte man etwas auch dort freigeben, wo es auch erstellt wurde. OnCreate > OnDesoroy Constructor > Destructor |
AW: Seltsames Verhalten der Destruktoren
Außerdem sind das (hoffentlich) 2 verschiedene Instanzen, einmal ein Feld des Frames und einmal des Formulars.
|
AW: Seltsames Verhalten der Destruktoren
Hi Delphi.Narium
Zitat:
TPDFiumFrame.Destroy will das Dokumentenhandle auf 0 setzen. Da dieses aber schon mit den Frameinstanzen der Mainform zerstört wurde, gibts das nicht mehr - und das gibteine AV. Zitat:
Schliesslich deklarierte ich die Liste auch in der Mainform, um die Zusammenhänge Mainform.Frameinstanzen und Basisframe zu dokumentieren. Die Einträge des Basisframes erfolgen nun immer in die Liste der Mainform. Das Entfernen der Deklaration etc. aus dem Frame ging dabei schlicht vergessen. Gruss Delbor |
AW: Seltsames Verhalten der Destruktoren
Hi zusammen
@DeddyH: Zitat:
@ himitsu Der Frame verfügt zumindest im OI über kein Property 'OLdCreateOrder', und dasjenige der Form steht auf false. Zitat:
Wie oben schon erwähnt, ist der PDFiumFrame Opensource, und ich bin nicht sein Autor. Bis auf die Erwähnten Änderungen ist der Code also Original. Gruss Delbor |
AW: Seltsames Verhalten der Destruktoren
Wenn ich das richtig Verstehe, hast du eine Form sowie zwei Frames. Desweiteren eine globale Instanz eines Dokumentes.
Wenn das so richtig ist, ists logisch das es kracht. Es wird versucht das Dokument freizugeben, obwohls schon im 1. Frame freigegeben wurde. Das zweite das mich ein wenig irritiert ist
Delphi-Quellcode:
Hier wird nichts freigeben, sondern lediglich ein Handle auf 0 gesetzt. Das ursprüngliche Handle existiert aber nach wie vor. Im besten fall ist sowas ein Memoryleak. :)
_Document := 0;
|
AW: Seltsames Verhalten der Destruktoren
Hallo,
was ist denn _Document für ein Typ? Setze einen Breakpoint und mache mal einen Watchpoint auf Self. Es könnte sein, dass das Frame bereits freigegeben ist. _Document := 0; ist ja zufällig die erste Codezeile. Drehe mal die ersten beiden Zeilen um, wo knallt es dann? |
AW: Seltsames Verhalten der Destruktoren
Hi Ghostwalker
Zitat:
Grundsätzlich existiert von einem (Basis-)Frame, derFrameklasse mit zugehöriger Unit, ja immer mindestens eine Frameinstanz. Zumindest dann, wenn der Frame auch verwendet werden soll. Der Basisframe ist im diesem Fall TPDFiumFrame. In die Mainform eingefügt sind PDFiumFrame1 und PDFiumFrame2 als 2 Instanzen des TPDFiumFrames. Und diese beiden Instanzen werden mit der Mainform bei Programmende zerstört - und damit auch das gerbte Handle (bzw. die Instanz (Kopie) davon. Das sind die Fehlermeldungen,, die ich in der Reihenfolge erhalte: Zitat:
Zitat:
Zitat:
Zitat:
Gruss Delbor |
AW: Seltsames Verhalten der Destruktoren
Hi Hoika
Document ist so deklariert:
Delphi-Quellcode:
Das Umdrehen der Codezeilen hat keine Änderung bewirkt.
FDocument : HPDFDocument;
... property _Document: HPDFDocument read FDocument write SetDocument; Gruss Delbor |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:40 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