[BUG in RC2 nicht gelöst] Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

[BUG in RC2 nicht gelöst] Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

Hallo,

Vielen Dank an die Lazarus Gemeinde für deren Weiterentwicklung :D !!!

Ich habe mir einmal das RC1 geladen und wollte das mit meinem "großen" Programm testen.

Ein paar Depreached korrigiert, dann ging es, also das Übersetzen lief soweit gut. :D

Jedoch wenn ich die EXE starte, dann stürzt die ab und verschwindet aus dem Speicher. Es kommt nur der Splash-Screen (der wird vor dem Main Formular erzeugt) und beim erzeugen des Main Formulares knallt es.
Das Problem ist folgendes:
Es werden von nicht sichtbaren TCheckBoxen irgend welche OnClick Events ausgelößt, da jedoch das ganze im Erstellen der Applikation noch ist und noch nicht alle Steuerelemente erzeugt wurden gibt es direkt eine Zugriffsverletzung und die EXE wirft sich weg.
Es muss unbedingt verhindert werden dass Events zu den Formular Steuerelementen gesendet werden, so lange das Formular nicht komplett erstellt wurde.
Den Quellcode kann ich dazu nicht veröffentlichen, das Formular hat ein paar tausen Steuerelemente drauf.
Ich hoffen dennoch, dass meine Beschreibung euch weiter hilft.

Damals, beim Umbau von Lazarus V1.8.x >>> V2.0RCx war der gleiche Bug eingebaut, vielleicht weis das noch jemand und kann das dann wieder beheben.

Verwendet: Offizieller Lazarus V3.0RC1 Download von der Subversion Seite.
Mit Lazarus V2.2.6 (letztes Release) gab es dieses Problem nicht.

Hintergrundinfo zum Splash-Screen Fenster: Meine EXE braucht beim RaspberryPi ca. 20 Sekunden bis die sich zeigte , daher habe ich erst den Splash Screen gezeigt (war ein must have), damit der Nutzer überhaupt sieht dass die EXE Lädt.

VG Markus
Zuletzt geändert von MmVisual am Mi 1. Nov 2023, 17:55, insgesamt 2-mal geändert.
EleLa - Elektronik Lagerverwaltung - www.elela.de

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

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von wp_xyz »

Hab gerade ein kleines Projekt gebastelt, das diverse Zustände und Events per WriteLn protokolliert, und da kommt während der Lade-Phase kein OnClick-Event der Checkbox. Aber vielleicht ist dieses Projekt auch zu einfach... Ich fürchte, da wirst du dein Projekt so weit verkleinern müssen, dass man den Fehler nachvollziehen kann.
Dateianhänge
checkbox_onclick_loading.zip
(2.06 KiB) 54-mal heruntergeladen

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von Jorg3000 »

Moin!
Ich habe v3.0 RC1 nicht, aber fände es äußerst merkwürdig, wenn LCL-Komponenten während der Erzeugungsphase eigenmächtig irgendwelche OnClick-Events feuern würden, denn das kann ja nur schief gehen.

Könnte es sein, dass du irgendwo beim Startvorgang eine eigene Initialisierung eingebaut hast, die z.B. ein .Click() oder .OnClick(...) manuell aufruft, um das Form mit Inhalten zu füllen?

Z.B. bei einem meiner Projekte erzeuge ich Fenster und Frames erst wenn der User entsprechende Programmteile aufruft. Dadurch braucht nicht schon beim Programmstart alles erzeugt zu werden, noch nicht gefüllt werden und noch keine Daten zum Füllen abgerufen worden. Dadurch kann das erste Fenster sofort angezeigt werden (bei mir ein Login-Fenster) und ich konnte auf einen Splash-Screen verzichten.

Dadurch, dass ich bei meinem Programm mit der bedarfsweisen Komponenten-Erzeugung nie sicher sein kann, ob eine betreffende Komponente schon existiert, habe ich mir angewöhnt, in allen Ereignissen vorab zu prüfen, ob darin verwendete Komponenten schon angelegt sind. Entweder kann ich die Komponente in dem Moment noch erzeugen oder ich breche die Procedure ab, z.B. ...

Code: Alles auswählen

if (self=nil) or (self.Frame1=nil) then Exit;
Dadurch, dass ich solche Prüfungen überall eingebaut habe, habe ich nun ein komplexes Programm mit rund 100 Fenstern, das aber ganz schlank und sofort startet. Vielleicht wäre so ein Vorgehen auch etwas für dein Projekt.
Grüße, Jörg

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

Meine Analyse zeigt dass es definitiv so ist wie ich beschrieben habe. Anbei ein Screenshot wenn ich ein Breakpoint setze wo beim Start eigentlich kein Event kommen sollte:
Diese "procedure TfrmMain.spFilterCaseExpClick(Sender: TObject);" wird von der Checkbox mit dem Name "chkSchnellsucheCaseExpSMD" aufgerufen (im Objektinspektor so verknüpft als OnClick Event)

Die Funktion "spFilterCaseExpClick()" wird noch manuell aus 3 anderen Position heraus angesprungen, da habe ich überall ein Breakpoint gesetzt, da kommt er definitiv nicht vorbei. Auch ist der Sender dieser 3 Funktionen nicht "chkSchnellsucheCaseExpSMD". Der Sender kann daher nur "chkSchnellsucheCaseExpSMD" sein wenn das OnClick Event von "chkSchnellsucheCaseExpSMD" geworfen wird. Und das darf nicht sein, weil man das Formular noch nicht einmal sieht, im Hintergrund der gelben Box sieht man nur einen Ausschnitt vom Splash Screen.

Im zweiten Screenshot suche ich nach "chkSchnellsucheCaseExpSMD", da sieht man dass nirgends imQuellcode das "Checked" von der Box manipuliert wird. Der einzige der das wohl macht ist das Formular selbst wenn Lazarus es im Speicher erzeugt. Daher vermute ich mal stark, dass genau während dem Create von dem Steuerelement Lazarus das OnClick Event generiert.

Im dritten Screenshot der Objektinspektor von "chkSchnellsucheCaseExpSMD". "AllowedGrayed" und State cbGrayed sind da aktiviert sowie Visible auf False.

Ich habe genau mit den gleichen Eigenschaften ein Demo geschrieben, das knallt mit exakt der gleichen Fehlermeldung.
Bild1.png
(272.44 KiB) Noch nie heruntergeladen
Bild2.png
Bild2.png (25.66 KiB) 3268 mal betrachtet
Bild3.png
Bild3.png (56.07 KiB) 3268 mal betrachtet
Zuletzt geändert von MmVisual am Sa 12. Aug 2023, 08:05, insgesamt 3-mal geändert.
EleLa - Elektronik Lagerverwaltung - www.elela.de

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

Das Demo-Projekt mit dem Fehler:
TCheckBoxTest.zip
(138.37 KiB) 46-mal heruntergeladen
@xp_xyz: Erweitere dein Demo noch bitte mit dieser Kombination aus meiner Demo :D
EleLa - Elektronik Lagerverwaltung - www.elela.de

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

@xp_xyz: Anbei dein Demo mit einer zweiten TCheckBox, das einen Laufzeitfehler generiert.
checkbox_onclick_loading.zip
(2.53 KiB) 55-mal heruntergeladen
EleLa - Elektronik Lagerverwaltung - www.elela.de

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

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von wp_xyz »

Kann das jetzt bestätigen. Aber es liegt nicht an der zweiten Checkbox, sondern daran, dass die zweite den State cbGrayed hat. Wenn ich in meinem ursprünglichen Projekt Checkbox1.State im O.I. auf cbGrayed setze, kann ich das Problem ebenfalls reproduzieren.

Das Problem entsteht, weil, wie du vermutet hast, OnClick ausgelöst wird, und in dem OnClick-Handler auf Label1 verwiesen wird, das noch gar nicht existiert.

Warum wird OnClick ausgelöst? Zunächst mal wird beim Streamen der State der Checkbox geändert, die ja mit State = cbUnChecked konstruiert worden ist. Dabei dabei wird TCheckbox.SetState aufrufen. Diese Routine führt zu

Code: Alles auswählen

procedure TCustomCheckBox.DoClickOnChange;
begin
  Changed;
  // emulate delphi OnClick behaviour (click will call OnChange)
  if not ClicksDisabled then
    inherited Click
  else
    DoOnChange;
end;
ClicksDisabled ist false, also geht's weiter in

Code: Alles auswählen

procedure TButtonControl.Click;
begin
  DoOnChange;
  inherited Click;
end;
mit

Code: Alles auswählen

procedure TButtonControl.DoOnChange;
begin
  if [csLoading, csDestroying, csDesigning] * ComponentState <> [] then Exit;
  EditingDone;
  if Assigned(OnChange) then OnChange(Self);
end;
Weil wir in der csLoading Phase sind wird DoOnChange gleich in der 1.Zeile verlassen:
Bleibt die von TControl geerbte Click Methode:

Code: Alles auswählen

procedure TControl.Click;

  function OnClickIsActionExecute: boolean;
  begin
    Result:=false;
    if Action=nil then exit;
    if not Assigned(Action.OnExecute) then exit;
    if not Assigned(FOnClick) then exit;
    Result:=SameMethod(TMethod(FOnClick),TMethod(Action.OnExecute));
  end;

var
  CallAction: Boolean;
begin
  //DebugLn(['TControl.Click ',DbgSName(Self)]);
  CallAction:=(not (csDesigning in ComponentState)) and (ActionLink <> nil);

  // first call our own OnClick if it differs from Action.OnExecute

  DebugLn(['CallAction = ', CallAction]);
  DebugLn(['OnClickIsActionExecute = ', OnClickIsActionExecute]);

  if Assigned(FOnClick)
  and ((not CallAction) or (not OnClickIsActionExecute)) then
    FOnClick(Self);
  // then trigger the Action
  if CallAction then
    ActionLink.Execute(Self);
end;
Ich habe hier zwei DebugLn-Anweisungen reingeschrieben, um zu sehen, wie die Bedingungen sind, damit der OnClick-Handler (FOnClick) ausgelöst werden könnte.

Und jetzt wird's mysteriös: Egal wie State eingestellt ist, wird für beide der Wert false ausgegeben (CallAction = false, OnClickIsActionExecute = false). "Not" macht daraus ein true, und weil Assigned(FOnClick) ebenfalls true ist, müsste FOnClick eigentlich immer ausgeführt werden ("if true and (true or true)" --> true). Dennoch geschieht dies nur wenn State = cbGrayed ist. Seltsam...

Aber egal was der Grund für dieses Verhalten ist, eigentlich würde man erwarten, dass während der Ladephase überhaupt keine Events getriggert werden. Jetzt ist aber TControl sehr zentral, und ich fürchte, wenn Delphi ein OnChange-Ereignis zu einem OnClick macht (* P.S.), gibt es noch mehrere solche Ungereimtheiten. Also: wenn man hier etwas ändert, hat das weitreichende Auswirkungen.

Ich denke, ich werde mal die anderen Entwickler kontaktieren...

Zur Sicherheit sollte man Event-Handler, die auf andere Controls zugreifen, immer vorzeitig verlassen, wenn "(csLoading in ComponentState)" ist. Wird bei 1000 Controls natürlich etwas lästig...

P.S.
Und bevor jemand sich wundert, warum OnClick ausgelöst wird, wo doch niemand geklickt hat: Das ist eine Unart, die uns Delphi ins Nest gelegt hat. Aber wenn das Event OnChange heißen würde, hätten wir dasselbe Problem.

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

Ich bin zuversichtlich, Lazarus bekommt das sicher besser hin als Delphi :D

In der Lazarus V2.x.x war das Problem noch nicht drin, ein Codevergleich sollte zeigen was da mal drin war bzw. jetzt anders ist.

Die Initialisierung der im Designer eingestellten Default Konfiguration (Objektinspektor) sollte während dem Start der EXE in keinem Steuerelement ein Event triggern.

Zusätzlich ist das Problem, dass wenn die EXE eine Exception in diesem Start-Zustand hat, dass die direkt abstürzt und man mittes Application.AddOnExceptionHandler() keine Chance hat etwas zu loggen oder anderweilig zu reagieren. Daher ist es wichtig dass der grundlegende Start der Lazarus Internas reibungslos läuft.
EleLa - Elektronik Lagerverwaltung - www.elela.de

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

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von wp_xyz »

MmVisual hat geschrieben:
Sa 12. Aug 2023, 11:50
In der Lazarus V2.x.x war das Problem noch nicht drin, ein Codevergleich sollte zeigen was da mal drin war bzw. jetzt anders ist.
Es gibt immer wieder das Problem, dass Projekte, die aus Delphi importiert werden, ein Checkbox.OnClick Event haben statt eines OnChange. Daher wurde versucht, das nachzurüsten - was nicht nur zu diesem Problem geführt hat.
MmVisual hat geschrieben:
Sa 12. Aug 2023, 11:50
Die Initialisierung der im Designer eingestellten Default Konfiguration (Objektinspektor) sollte während dem Start der EXE in keinem Steuerelement ein Event triggern.
Diese Aussage ist mir zu allgemein - und auch bei OnChange/OnClick vermute ich, dass es irgendwelche kombinierten Controls gibt, die sich genau darauf verlassen, dass sie auch während der Ladephase über diese Events miteinander kommunizieren können.

Ich finde, wenn du sichergehen willst, solltest du in die OnChange/OnClick-Handler von Controls, die auf andere Controls zugreifen, prüfen, ob die anderen Controls auch wirklich existieren - darauf kannst du dich nämlich nicht verlassen: Eine unüberlegte und wenig verwendete Routine kann genau so ein Control gelöscht haben, und dann hast du wieder diesen Absturz, nur dass er nun nicht so auffälltig beim Programmstart erfolgt, sondern vielleicht erst dann, wenn der User seinen langen Text eingetippt und noch nicht gespeichert hat...

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

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von wp_xyz »

Ondrej hat geantwortet, dass das Problem an der Reihenfolge der published-Properties in der lfm-Datei liegt. Denn diese werden von oben nach unten gelesen. Wenn man die Events konsequent ans Ende der published-Deklarationen stellt, können die Property-Werte gelesen werden, ohne Events auszulösen - weil es diese ja noch gar nicht gibt.

Mit seiner Änderung, die Events ans Ende zu stellen, ist das Problem - zumindest in meinem Demo-Projekt - behoben. Du kannst das mit deiner aktuellen Version der Unit stdctrls.pp selbst machen (oder auf v3.0RC2 warten - ich habe seine Änderungen nach fixes_3_0 übertragen). Falls du die Änderung gleich ausprobierst, musst du die IDE neu kompilieren und die betroffenen Formulare neu speichern (damit die Reihenfolge neu geschrieben wird). Und beachte auch, dass nicht nur TCheckbox von diesem Problem betroffen ist.

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

Vielen Dank für das schnelle Fixen.

Etwas während dem Erzeugen ist, wie schon gesehen, tötlich für die EXE.
Hingegen wenn nach dem Erzeugen etwas aufgerufen wird, so ist es richtig, sonst würde auch niemals das Event Form.OnCreate kommen.

In diesem OnCreate rufe ich dann immer diese Funktionen auf, die es unbedingt benötigt, also z.B. irgend ein OnClick Events oder anderes zum initialisieren. So etwas sollte Lazarus natürlich nicht sporadisch von alleine machen, was zum einen Delphi auch nicht macht und zum anderen kann Lazarus nicht wissen welche OnClick Events am Start gesendet werden sollen und welche nicht.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6217
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: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von af0815 »

Schon bei Delphi oder gerade deswegen habe ich mir angewöhnt mich absolut nicht auf die Erstellreihenfolge des Systems zu verlassen. Es gibt bei mir ein globales Flag, das mir sagt, das das System alles erstellt hat und erst dann lasse ich meine Events arbeiten, notfalls werden die zugleich jetzt erst richtig zugewiesen. Und eine Abfrage ob ein anders Objekt existiert ist Standard. Ein Programm besteht aus 60% aus reiner Fehler (oder Verhinderung) Kontrolle, erst der Rest ist das eigentliche Programm.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

@af0815
Das mache ich ebenfalls, nur anders. Ich lasse einen Timer anfang laufen, der beim ersten mal dann gleich deaktiviert wird. Die geringe Zeit von 10ms reicht aus dass das Formular komplett sichtbar ist und alle Events vom Startup haben automatisch Vorrang vor dem ersten Timer Event.
Die um 10ms verzögerte Aktivierung der Datenbank merkt niemand, bzw. man sieht schon mal die nackte/leere EXE, denn das Datenbank öffnen kann schon mal je nach Verbindung und Datenmenge einen Augenblick dauern.
EleLa - Elektronik Lagerverwaltung - www.elela.de

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von MmVisual »

@wp_xyz:
Ich habe das aktuelle Lazarus installiert (mit FpcUpDeluxe, Lazarus trunk + FPC stable):
21:08:00 IDE: Lazarus LCL 3.99.0.0, Free Pascal FPC 3.2.2

Der Bug ist behoben, die "große" Exe startet nun bei mir. Vielen Dank nochmals. :D
EleLa - Elektronik Lagerverwaltung - www.elela.de

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

Re: Lazarus V3.0 RC1 Fehler bei Programmstart der kompillierten EXE

Beitrag von fliegermichl »

MmVisual hat geschrieben:
Sa 12. Aug 2023, 13:34
Vielen Dank für das schnelle Fixen.

Etwas während dem Erzeugen ist, wie schon gesehen, tötlich für die EXE.
Hingegen wenn nach dem Erzeugen etwas aufgerufen wird, so ist es richtig, sonst würde auch niemals das Event Form.OnCreate kommen.

In diesem OnCreate rufe ich dann immer diese Funktionen auf, die es unbedingt benötigt, also z.B. irgend ein OnClick Events oder anderes zum initialisieren. So etwas sollte Lazarus natürlich nicht sporadisch von alleine machen, was zum einen Delphi auch nicht macht und zum anderen kann Lazarus nicht wissen welche OnClick Events am Start gesendet werden sollen und welche nicht.
Jedes Control hat die virtuelle Methode Loaded. Diese wird aufgerufen, nachdem alles vollständig geladen ist.
OnCreate ist zu früh.

Antworten