[ Gelöst ] Application.CreateForm(...

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

[ Gelöst ] Application.CreateForm(...

Beitrag von Niesi »

Hallo,

ich habe da eine Verständnisfrage (eigentlich versuche ich was ganz anderes zu verstehen, ein Problem in der Pdfium, aber da sprang mich was an):

Wenn ich einem Projekt eine Unit mit Form zuweise, dann wird in der lpr automatisch ein Application.CreateForm(... erzeugt. Trotzdem muss ich in meinem MainForm den InfoForm mit

"MyInfoForm := tMyInfoForm.Create(Self);"

erzeugen, sonst gibt's einen SIGSEGV.

Warum das denn? Die Form ist doch da, existiert, oder?

Gleichzeitig darf ich in Destructor meiner MainForm die MyInfoForm aber nicht mit Free freigen, denn sonst gibt es zum Abschluss einen SIGSEGV.

Kommentiere ich in der lpr das "Application.CreateForm(TMyInfoForm, MyInfoForm);" aus, so läuft alles so, wie ich es von der Logik her erwartet habe.

Weiß wer, warum ich ich trotz "Application.CreateForm(TMyInfoForm, MyInfoForm);" in der lpr noch den MyInfoForm in meinem Constructor erzeugen muss, ihn dann aber nicht "destroyen" darf?



Ich hänge mein Beispiel mal hier ran, falls mein Text nicht verständlich genug ist - wie geschrieben, ich suchte eigentlich andere Antworten, daher ist da noch anderes Zeugs dabei ...


UsesTest.7z
(172.84 KiB) 99-mal heruntergeladen
Zuletzt geändert von Niesi am Mo 18. Nov 2024, 16:43, insgesamt 1-mal geändert.
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6782
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von af0815 »

Ich habe mich auch schon sowas mal gefragt - bin damals zu dem Schluss gekommen, das das mit der initialsieren des Applikationsobjektes zusammenhängt, das bei GUIs ja auch das ganze GUI Framework im Hintergrund initialisieren muss. Ausserdem werden zum Beispiel die Messagequece an das erste Form gebunden, weil irgendwer muss ja Botschaften empfangen. Kurzum alles was den Komfort von RAD wird im Hintergrund zugewiesen.

Ist aber schon länger her, weil ich habe damals was mit den Frames gesucht und bin dabei ziemlich tief in die Materie eingetaucht - ohne es zu wollen :-)

----
Entweder du gibst die Kontrolle über das Formular an Lazarus ab - dann Autocreate über die LPR - oder du machst alles selbst, dann kein Eintrag in der LPF und die VAR definition im Infoform kannst du dir sparen (ich lösche die immer, damit ich nicht falsch auf was zugreife).

Code: Alles auswählen

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, infoform;

type

  { TMainForm }

  TMainForm = class(TForm)
    MyMemo: TMemo;
  private
    MyInfoForm: TMyInfoForm;
  public
    constructor Create(aOwner: tComponent); override;
    destructor Destroy; override;
  end;
Edit:
Dein Code geht deswegen nicht, weil du im Create bereits das Info Fenster aufrufst und das ist ja zu diesem Zeitpunkt noch nicht initialisiert (Wäre erste der nächste Schritt im lpr). Man sieht es , wenn man sich den Call Stack ansieht. Dein Problem ist, das du die Reihenfolge auch nicht umdrehen kannst, weil ja das erste Form das "MainForm" ist das mit Run ja auch aufgerufen wird. Deswegen mache ich alle Initialisierunegn und erzeugen von Formularen, DataModulen etc. immer erst im ersten AUfruf von OnActivate, weil dort sind alle bisherigen Creates bereits durch und ich habe die Möglichkeit genau die Lebensdauer zu definieren.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Mathias
Beiträge: 6919
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Application.CreateForm(...

Beitrag von Mathias »

Wenn ich einem Projekt eine Unit mit Form zuweise, dann wird in der lpr automatisch ein Application.CreateForm(... erzeugt. Trotzdem muss ich in meinem MainForm den InfoForm mit

"MyInfoForm := tMyInfoForm.Create(Self);"

erzeugen, sonst gibt's einen SIGSEGV.
Du machst ein Show von einem Form, das es gar noch nicht gibt.

Code: Alles auswählen

//  MyInfoForm := tMyInfoForm.Create(Self);
  MyInfoForm.Show;
Darum habe ich die Zeilen da vertauscht, und siehe da, es geht auf einmal,

Code: Alles auswählen

  Application.CreateForm(TMyInfoForm, MyInfoForm);
  Application.CreateForm(TMainForm, MainForm);

Was man noch machen kann, überprüfen, ob es nicht nil ist,

Code: Alles auswählen

  if MyInfoForm = nil then begin
    ShowMessage('nil');
    exit;
  end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von Niesi »

Mathias hat geschrieben: So 17. Nov 2024, 14:20
Wenn ich einem Projekt eine Unit mit Form zuweise, dann wird in der lpr automatisch ein Application.CreateForm(... erzeugt. Trotzdem muss ich in meinem MainForm den InfoForm mit

"MyInfoForm := tMyInfoForm.Create(Self);"

erzeugen, sonst gibt's einen SIGSEGV.
Du machst ein Show von einem Form, das es gar noch nicht gibt.

Code: Alles auswählen

//  MyInfoForm := tMyInfoForm.Create(Self);
  MyInfoForm.Show;
Darum habe ich die Zeilen da vertauscht, und siehe da, es geht auf einmal,

Code: Alles auswählen

  Application.CreateForm(TMyInfoForm, MyInfoForm);
  Application.CreateForm(TMainForm, MainForm);

Was man noch machen kann, überprüfen, ob es nicht nil ist,

Code: Alles auswählen

  if MyInfoForm = nil then begin
    ShowMessage('nil');
    exit;
  end;
Da hast Du Recht - und das ist auch logisch. Weil ich den Constructor überschrieben habe, passt die Reihenfolge in der lpr nicht mehr.

Ok. Den Punkt hast Du geklärt. Danke :!:

Bleibt noch die Frage: Warum erzeugt ein MyInfoForm.Free ein SIGSEGV? Irgendwie habe ich abgespeichert, dass bei Free geprüft wird, ob überhaupt etwas destroyed werden kann / muss und es nichts ausmacht, wenn das gar nicht der Fall ist ...

Liege ich da falsch?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Soner
Beiträge: 726
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Application.CreateForm(...

Beitrag von Soner »

Du benutzt MyInfoForm schon in Constructor von Mainform. Das System noch keine Gelegenheit gehabt MyInfoForm zu erstellen.
Wenn du MyInfoForm später benutzt, z.B. durch Benutzerinteraktion, dann passiert nichts, auch wenn du es in Mainform freigibst passiert nichts.

Noch etwas, die erste Form die man in LPR-Datei mit Application.CreateForm erstellt wird Hauptform (Application.Mainform) und wenn man Hauptform schließt, dann wird das Programm beendet.

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von Niesi »

Soner hat geschrieben: So 17. Nov 2024, 19:23 Du benutzt MyInfoForm schon in Constructor von Mainform. Das System noch keine Gelegenheit gehabt MyInfoForm zu erstellen.
Wenn du MyInfoForm später benutzt, z.B. durch Benutzerinteraktion, dann passiert nichts, auch wenn du es in Mainform freigibst passiert nichts.

Noch etwas, die erste Form die man in LPR-Datei mit Application.CreateForm erstellt wird Hauptform (Application.Mainform) und wenn man Hauptform schließt, dann wird das Programm beendet.
Ja, das mit dem Aufruf von MyInfoForm VOR der Erstellung hatte Mathias schon geklärt. Und dass die ertse in der lpr erstellte Form dann die Hauptform ist, das wusste ich noch.

Was mit fehlt, ist der Grund für den SIGSEGV, wenn ich "MyInfoForm.Free;" aufrufe. Sollte Free nicht so sein, dass das Objekt "destroyed" wird, wenn es noch existiert, aber nichts passiert, wenn es bereits erledigt ist?

Habe ich das falsch im Kopf?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1647
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Application.CreateForm(...

Beitrag von fliegermichl »

Normale globale Variablen sind nicht initialisiert.
D.h. die Form wurde noch nicht erzeugt aber der Variableninhalt ist nicht nil und das sorgt für die Exception.

wp_xyz
Beiträge: 5154
Registriert: Fr 8. Apr 2011, 09:01

Re: Application.CreateForm(...

Beitrag von wp_xyz »

Niesi hat geschrieben: Mo 18. Nov 2024, 12:48 Was mit fehlt, ist der Grund für den SIGSEGV, wenn ich "MyInfoForm.Free;" aufrufe. Sollte Free nicht so sein, dass das Objekt "destroyed" wird, wenn es noch existiert, aber nichts passiert, wenn es bereits erledigt ist?
Bitte poste ein kleines Projekt, in dem man das nachvollziehen kann. Ich weiß, im 1.Post hängt ein Projekt dran, aber im Lauf der Diskussion kamen einige Vorschläge, und mir ist nicht klar, von welchem Status des Projekts du jetzt ausgehst.

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von Niesi »

wp_xyz hat geschrieben: Mo 18. Nov 2024, 14:51
Niesi hat geschrieben: Mo 18. Nov 2024, 12:48 Was mit fehlt, ist der Grund für den SIGSEGV, wenn ich "MyInfoForm.Free;" aufrufe. Sollte Free nicht so sein, dass das Objekt "destroyed" wird, wenn es noch existiert, aber nichts passiert, wenn es bereits erledigt ist?
Bitte poste ein kleines Projekt, in dem man das nachvollziehen kann. Ich weiß, im 1.Post hängt ein Projekt dran, aber im Lauf der Diskussion kamen einige Vorschläge, und mir ist nicht klar, von welchem Status des Projekts du jetzt ausgehst.
Ich habe jetzt eine Änderung vorgenommen, da ich MyInfoForm nicht als MainForm haben möchte. Daher muss jetzt im Menü das Anzeigen des OS per Mausklick gestartet werden. Nach dem MyInfoForm.Free; gibt es einen Fehler. Und ich habe im Kopf, dass das mit Free nicht passieren sollte ...

14~OSDetection&UsesTest.7z
(173.27 KiB) 91-mal heruntergeladen

Jedenfalls Danke an ALLE für die Mühe ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

wp_xyz
Beiträge: 5154
Registriert: Fr 8. Apr 2011, 09:01

Re: Application.CreateForm(...

Beitrag von wp_xyz »

Warum willst du MyInfoForm überhaupt zerstören? Es wurde automatisch von Application erzeugt, also kümmert sich auch Application ums Aufräumen.

Zur Schutzverletzung kommt es, weil Application MyInfoForm NACH MainForm erzeugt hat. Beim Aufräumen ist die Reihenfolge umgekehrt, also zuerst wird MyInfoForm zerstört, dann MainForm. Wenn aber MainForm MyInfoForm selbst nochmal zerstören will, gibt es dieses schon nicht mehr

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von Niesi »

wp_xyz hat geschrieben: Mo 18. Nov 2024, 15:55 Warum willst du MyInfoForm überhaupt zerstören? Es wurde automatisch von Application erzeugt, also kümmert sich auch Application ums Aufräumen.

Zur Schutzverletzung kommt es, weil Application MyInfoForm NACH MainForm erzeugt hat. Beim Aufräumen ist die Reihenfolge umgekehrt, also zuerst wird MyInfoForm zerstört, dann MainForm. Wenn aber MainForm MyInfoForm selbst nochmal zerstören will, gibt es dieses schon nicht mehr
Ja, das habe ich mit diesem Thread gelernt - aber sollte Free dann nicht einfach ignoriert werden?

Hab' ich das falsch aufgefasst?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

hansotten
Beiträge: 3
Registriert: Mo 22. Jun 2020, 08:47

Re: Application.CreateForm(...

Beitrag von hansotten »

Der Lazarus-Weg, besteht darin, den Objektinspektor des Hauptformulars zu verwenden und dort unter Events die Option OnCreate auszuwählen. Füllen Sie dann die Prozedur mainform.OnCreate aus, die erscheint. Verwenden Sie nicht die Konstruktor-/Destruktor-Konstruktion. Schauen Sie sich einige einfache Beispiele im Lazarus-Wiki an.

Ich habe Ihr Programm auf die Standard-OnCreate-Nutzung von Lazarus umgestellt. Läuft einwandfrei.
Dateianhänge
14~OSDetection&UsesTest.zip
(140.23 KiB) 98-mal heruntergeladen

wp_xyz
Beiträge: 5154
Registriert: Fr 8. Apr 2011, 09:01

Re: Application.CreateForm(...

Beitrag von wp_xyz »

Niesi hat geschrieben: Mo 18. Nov 2024, 15:57 Ja, das habe ich mit diesem Thread gelernt - aber sollte Free dann nicht einfach ignoriert werden?
Wieso denn? Wie soll dein MainForm überhaupt mitkriegen, dass MyInfoForm vorher schon zerstört worden ist? Das sind zwei unabhängige Objekte, die nichts voneinander wissen. Gut, MyInfoForm könnte sich beim Zerstören auf nil setzen, das du dann in MainForm abfragen könntest. Aber das ist keinesfalls garantiert.

Folge einfach der Grundregel: Für das Zerstören eines Objects ist derjenige verantwortlich, der es erzeugt hat. Oder anders herum: Zerstöre nur das, was du selbst erzeugt hast

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 587
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Application.CreateForm(...

Beitrag von Niesi »

Ok, habi was gelernt ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Antworten