Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   JCL Stack Exception unter Firemonkey in Win64/32 (https://www.delphipraxis.net/199226-jcl-stack-exception-unter-firemonkey-win64-32-a.html)

Christoph Schneider 7. Jan 2019 15:21

JCL Stack Exception unter Firemonkey in Win64/32
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hat schon jemand JclLastExceptStackListToStrings von JclDebug in einer Windows Firemonkey Applikation zur Call-Stack-Ausgabe nach einer Exception eingesetzt?

Ich versuche unter Delphi 10.2 in einer Firemonkey Applikation dieses Teil das erste mal auch unter Firemonkey einzubauen und bekomme dabei unter Win64 wie auch unter Win32 ein unterschiedlichen und irreführenden Stacks mit Einträgen die ich mir nicht erklären kann.

Meine Test-Applikation löst auf tastenklick eine Exception aus und ist ganz einfach:

Delphi-Quellcode:

uses
  JclDebug;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Application.OnException := ExceptionHandler;
end;

procedure TForm2.ExceptionHandler(Sender: TObject; E: Exception);
begin
  ListBox1.Clear;
  ListBox1.Items.Add('Exception Class : ' +  E.ClassName);
  ListBox1.Items.Add('Exception Message: ' +  E.Message);
  JclLastExceptStackListToStrings(ListBox1.Items);
end;

procedure TForm2.Button1Click(Sender: TObject);

  procedure DivByZeroTest(zero: integer);
  begin
    Caption := IntTostr(3 div zero);
  end;

var
  n: TForm;
begin
  n := pointer(1);
  case ComboBox1.ItemIndex of
    0: DivByZeroTest(ComboBox1.ItemIndex);
    1: n.Free;
    2: n.Show;
  end;
end;

initialization
  Include(JclStackTrackingOptions, stRawMode);
  JclStartExceptionTracking;
finalization
  JclStopExceptionTracking;
end.
Im Anhang zeige ich die unterschiedlichen Ausgabe der Release-Konfiguration für Win32/Win64 Plattformen.
In der Debug-Konfiguration sehe ich nur kleine Abweichungen zum Release-Stack, wobei vermutlich die Compiler Optimierung die Differenz erklären kann.

Hat jemand eine Idee an was es liegen könnte oder funktioniert JCLDebug under FMX grundsätzlich nicht?

Setzt jemand bereits erfolgreich eine Käufliche Kompetente unter Firemonkey ein? Gibt es eine Lösung die auf allen Plattformen läuft? (MacOS, iOS, Android?)

Der schöne Günther 8. Jan 2019 07:51

AW: JCL Stack Exception unter Firemonkey in Win64/32
 
Sieht bei mir unter 10 Seattle ähnlich aus. Als "funktioniert nicht" würde ich es jetzt nicht abstempeln, es ist ja nur zusätzlicher Müll drin - Das Wichtige (Button1Click, gefolgt von DivByZeroTest) ist ja drin 🤷

Für MacOS kenne ich nichts, für iOS und Android habe ich mal gesehen dass diese Zauberer mal etwas gebastelt hatten:

Christoph Schneider 8. Jan 2019 10:24

AW: JCL Stack Exception unter Firemonkey in Win64/32
 
@Günther: Ja, es stimmt, einen Hinweis auf den Fehler kann man mit dieser Lösung auf jeden Fall bekommen. Nur bei der Fehlersuche nach sporadischen Race-Conditions ist es schon schwierig genug, denn Fehler zu finden. Einen auch nur teilweise falschen Stack kann einen aber auch auf eine falsche Fährte locken und es gibt einem jedenfalls nicht ein besseres Vertrauen. :oops:

Wieso Embarcadero nicht bereits einen brauchbaren Call-Stack in der RTL für alle Exceptions implementiert hat, ist mir schon ein kleines Rätsel. Ich bin sicher nicht der einzige der sowas vermisst.

Christoph Schneider 8. Jan 2019 16:47

AW: JCL Stack Exception unter Firemonkey in Win64/32
 
Nach einiges Recherche und analysieren des JCLDebug Codes habe ich eine Lösung gefunden, die mal das tut, was ich erwartete.

Ich habe dabei den TJclStackInfoList.IgnoreLevels http://wiki.delphi-jedi.org/JCL_Help...t.IgnoreLevels
abhängig vom Compiler erhöht. Wieso jetzt für den IgnoreLevel eine 10 für Windows 64 und eine 32 für Windows 32 eingesetzt wird, konnte ich leider nur experimentell ermitteln und kenne die Details dazu nicht. Ich vermute, dass bei FMX der Exception-Handler etwas anders gelöst ist als bei der VCL und dieser IgnoreLevel hilft, jenen Stack-Teil des etwas grösseren FMX-Exception-Handlers zu verstecken.

Mit folgendem Code überschreibe ich die Standard-Lösung von JCLDebug. Vielleicht hilft es ja auch anderen weiter:

Delphi-Quellcode:
function GetExceptionStackInfoProc(P: System.PExceptionRecord): Pointer;
var
  LLines: TStringList;
  LText: String;
  LResult: PChar;
  jcl_sil: TJclStackInfoList;
begin
  LLines := TStringList.Create;
  try
  {$IFDEF WIN64}
    jcl_sil := TJclStackInfoList.Create(true, 10, p.ExceptionAddress, false, nil, nil);
  {$ENDIF}
  {$IFDEF WIN32}
    jcl_sil := TJclStackInfoList.Create(true, 32, p.ExceptionAddress, false, nil, nil);
  {$ENDIF}
    try
      jcl_sil.AddToStrings(LLines);
    finally
      FreeAndNil(jcl_sil);
    end;
    LText := LLines.Text;
    LResult := StrAlloc(Length(LText));
    StrCopy(LResult, PChar(LText));
    Result := LResult;
  finally
    LLines.Free;
  end;
end;

function GetStackInfoStringProc(Info: Pointer): string;
begin
  Result := string(PChar(Info));
end;

procedure CleanUpStackInfoProc(Info: Pointer);
begin
  StrDispose(PChar(Info));
end;

initialization
  if JclStartExceptionTracking then
  begin
    Exception.GetExceptionStackInfoProc := GetExceptionStackInfoProc;
    Exception.GetStackInfoStringProc := GetStackInfoStringProc;
    Exception.CleanUpStackInfoProc := CleanUpStackInfoProc;
  end;

finalization
  if JclExceptionTrackingActive then
  begin
    Exception.GetExceptionStackInfoProc := nil;
    Exception.GetStackInfoStringProc := nil;
    Exception.CleanUpStackInfoProc := nil;
    JclStopExceptionTracking;
  end;

end.
Danach muss man nur noch in der Application.OnException methode den E.StackTrace auswerten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:23 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