Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Program crasht beim Schließen, aber... (https://www.delphipraxis.net/203495-program-crasht-beim-schliessen-aber.html)

himitsu 25. Feb 2020 14:19

AW: Program crasht beim Schließen, aber...
 
Form1 oder acDateiSpeichern ist dann wohl nil/ungültig.

freejay 25. Feb 2020 14:53

AW: Program crasht beim Schließen, aber...
 
Zitat:

Zitat von himitsu (Beitrag 1458329)
Form1 oder acDateiSpeichern ist dann wohl nil/ungültig.

Die Zuweisung an die Action acDateiSpeichern löst eine Übertragung des Enabled-Status auf Controls, die diese Action als Action eingebunden haben aus. Und da geht's schief (Unit System.Action):


Delphi-Quellcode:
procedure TContainedAction.SetEnabled(Value: Boolean);
var
  I: Integer;
begin
  if Value <> FEnabled then
  begin
    if Assigned(ActionList) then
    begin
      if ActionList.State = asSuspended then
      begin
        FEnabled := Value;
        Exit;
      end
      else if (ActionList.State = asSuspendedEnabled) then
        Value := True;
    end;
    for I := 0 to ClientCount - 1 do
      if Clients[I] is TContainedActionLink then
        TContainedActionLink(Clients[I]).SetEnabled(Value); // <<<<<<<<<<<<<<<<<<<<<<<<<<<
    FEnabled := Value;
    Change;
  end;
end;
Wenn mir jetzt jemand verraten könnte, wie ich an den Namen des Controls, das mittels Client[i] mit der Action verbunden ist, rankomme...

himitsu 25. Feb 2020 17:56

AW: Program crasht beim Schließen, aber...
 
ActionLink.Action.ActionComponent ?

Wenn das nicht hilft, dann könnte man sich noch aus ActionLink.OnChange das Objekt des Methoden-Zeigers extrahieren.

freejay 27. Feb 2020 10:49

AW: Program crasht beim Schließen, aber...
 
Vielen Dank für die Tipps!

Ich konnte das Problem, das offenbar sowohl für den Crash beim Start (nur im Debug-Modus) als auch beim Beenden (nur im Release-Modus) verantwortlich war, finden:

Delphi-Quellcode:
TAction(Sender).Checked := true;


Diese unscheinbare Zeile wurde leider in einem Fall mit dem Formular als Sender aufgerufen... Das schreibt halt das true irgendwohin... Obwohl dieser Fehler da "schon immer" drin gewesen ist, hatte er wohl erst jetzt durch Erweiterungen des Codes (oder Änderungen in Bibliotheken) Auswirkungen.

Die ersten Tests lassen mich jedenfalls hoffen, dass das tatsächlich die Ursache für die Probleme war.

Puh!

Rolf Frei 27. Feb 2020 13:20

AW: Program crasht beim Schließen, aber...
 
Glückwunsch, dass du es gefunden hast. Sowas kann bei einem Hardcast passierern. Würdest du (Sender as TAction).Checked schreiben, hättest du eine Exception "Ungültige Typumwandlung" erhalten.

freejay 27. Feb 2020 13:24

AW: Program crasht beim Schließen, aber...
 
Zitat:

Zitat von Rolf Frei (Beitrag 1458530)
Glückwunsch, dass du es gefunden hast. Sowas kann bei einem Hardcast passierern. Würdest du (Sender as TAction).Checked schreiben, hättest du eine Exception "Ungültige Typumwandlung" erhalten.

Gut zu wissen! Der Unterschied war mir nicht bewusst. Ich vermeide Zeiger und Typumwandlungen fast vollständig, daher bin ich da nicht so firm... :roll:

himitsu 27. Feb 2020 14:02

AW: Program crasht beim Schließen, aber...
 
Bei einer harten Typkonvertierung wird der Typ der Variable direkt geändert und man sagt dem Compiler das ist jetzt so. (der Compiler macht da nur noch eine Prüfung auf die Speichergröße der Typen) und zur Laufzeit ist das dann alles direkt so.

bei der "weichen" Konvertierung prüft er Compiler nur auf Verwandtschaft von Variablen-Typ und Zieltyp und zur Laufzeit wird eine Funktion aufgerufen, die intern den "aktuellen" Typ prüft und im Fehlerfall eine Exception wirft.
als Generic kannst dir dieses etwa so vorstellen
Delphi-Quellcode:
// (X as T) = AsClass<T>(X) bzw. T(_AsClass(X, T))

function AsClass<T>(Source: TObject): T;
begin
  if not (Source is T) then // if not _IsClass(Source, T) then .... ja, auch das IS ist soeine Funktion
    raise EInvalidCast.Create(SInvalidCast);
  Result := T(Source);
end;

// das Original aus System.pas, welches der Compiler dort aufruft, wo jemand das AS benutzt
function _AsClass(Child: TObject; Parent: TClass): TObject;
{$IFDEF PUREPASCAL}
begin
  Result := Child;
  if not (Child is Parent) then
    Error(reInvalidCast);  // loses return address
end;
{$ELSE}
...


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:32 Uhr.
Seite 3 von 3     123   

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