AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Seltsames Verhalten der Destruktoren

Ein Thema von Delbor · begonnen am 12. Dez 2017 · letzter Beitrag vom 13. Dez 2017
Antwort Antwort
Seite 1 von 2  1 2      
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#1

Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 11:43
Delphi-Version: XE8
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:
procedure TSynpdfMain.FormDestroy(Sender: TObject);
begin
  Self.WriteReportFile;
  FReportList.Free;
end;
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.

Seit neuestem (heute) erhalte ich aber eine neue AV, und zwar hier:
Delphi-Quellcode:
destructor TPDFiumFrame.Destroy;
begin
  _Document := 0;
  FPages.Free;
  PDFPageClass.Free;
  FReportList.Free;
  inherited;
end;
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

_Document := 0;
Der Vollständigkeit halber hier auch noch die beiden Constructoren:

Delphi-Quellcode:
procedure TSynpdfMain.FormCreate(Sender: TObject);
begin
  FReportList := TStringlist.Create;
  FReportList.Sorted := False;
  FReportList.Add('________________________________________');
  FReportList.Add('procedure TSynpdfMain.FormCreate;');
  FReportList.Add('________________________________________');
end;
und
Delphi-Quellcode:
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;
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).

Gerade getestet und ebenso falsch:

Delphi-Quellcode:
  if _Document > 0 then
    _Document := 0;
Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#2

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 11:52
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?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.135 Beiträge
 
Delphi 12 Athens
 
#3

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 12:02
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.
> Delphi-Referenz durchsuchenFreeAndNil

Aber grundsätzlich sollte man etwas auch dort freigeben, wo es auch erstellt wurde.
OnCreate > OnDesoroy
Constructor > Destructor
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (12. Dez 2017 um 12:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 12:04
Außerdem sind das (hoffentlich) 2 verschiedene Instanzen, einmal ein Feld des Frames und einmal des Formulars.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 12:15
Hi Delphi.Narium

Zitat:
Wenn im Programmablauf TPDFiumFrame.Destroy vor TSynpdfMain.FormDestroy...
Es ist ja eben gerade umgekehrt. Es ist auch nicht die Liste, die die AV auslöst.

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:
Ausserdem wird FReportList in TPDFiumFrame.Destroy und TSynpdfMain.FormDestroy freigegeben. Warum?
Anfänglich hatte ich diese Liste im Frame deklariert - dieser ist Opensource und stammt nicht von mir, und so wollte ich mir über die Abläufe klar werden.
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
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (12. Dez 2017 um 12:40 Uhr)
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 12:38
Hi zusammen

@DeddyH:
Zitat:
Außerdem sind das (hoffentlich) 2 verschiedene Instanzen, einmal ein Feld des Frames und einmal des Formulars.
Falls du die Reportliste meinst: ja, sind sie.

@ himitsu
Der Frame verfügt zumindest im OI über kein Property 'OLdCreateOrder', und dasjenige der Form steht auf false.

Zitat:
Aber grundsätzlich sollte man etwas auch dort freigeben, wo es auch erstellt wurde.
OnCreate > OnDesoroy
Constructor > Destructor
Wenn vorhanden, bzw. wenn es Sinn macht, benutze ich immer das OnCreate-Event, um etwas zu initialisieren. Frames haben kein (Published)-Event OnCreate, wesshalb hier sowas immer im Costructor/Destructor geschieht.
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
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 12:58
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

  _Document := 0; 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.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.270 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 13:06
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?
Heiko
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 13:35
Hi Ghostwalker

Zitat:
Wenn ich das richtig Verstehe, hast du eine Form sowie zwei Frames. Desweiteren eine globale Instanz eines Dokumentes.
Jein - es gibt nur einen Basisframe, davon aber zwei Frameinstanzen. Das nur mal, um 'alle Klarheiten zu beseitigen'.
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:
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt SynpdfTestProject.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x006476ae: read of address 0x000002c8' aufgetreten.
---------------------------
Zitat:
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt SynpdfTestProject.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x005c7d73: read of address 0x00000010' aufgetreten.
---------------------------
Zitat:
Synpdftestproject
---------------------------
Zugriffsverletzung bei Adresse 005C7D73 in Modul 'SynpdfTestProject.exe'. Lesen von Adresse 00000010.
---------------------------

Zitat:
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt SynpdfTestProject.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x005c7d73: read of address 0x00000010' aufgetreten.
---------------------------
Wichtig: Diesa habe ich erst seit heute, ohne auch nur die kleinste Änderung vorgenommen zu haben. Insbesondere sind im Framedestruktor ausser den dokumentierten Änderungen keine solchen vorgenommen worden.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Seltsames Verhalten der Destruktoren

  Alt 12. Dez 2017, 13:49
Hi Hoika
Document ist so deklariert:

Delphi-Quellcode:
FDocument : HPDFDocument;
...
 property _Document: HPDFDocument read FDocument write SetDocument;
Das Umdrehen der Codezeilen hat keine Änderung bewirkt.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:05 Uhr.
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