Auslöser einer Exception in compilierter Version?

Ich habe die Betriebssoftware für einen Verkaufsautomaten in Xojo 2021 geschrieben, läuft auf einem Raspberry 3B+.

Die Software läuft normalerweise 24h problemlos durch, bevor sie selbst aus Sicherheitsgründen jeden Morgen gegen 5 Uhr einen Neustart auslöst. Allerdings kommt es selten (ca. 1x in 10 Tagen) zu einer “exception out of bounds”, die das System lahm legt. Ist zwar sehr selten, aber trotzdem extrem ärgerlich. Im Debug-Mode tritt das zu selten auf, um es einzugrenzen.

Wie kann ich feststellen, welcher Programmteil, welche Klasse oder was auch immer der Auslöser ist? In der Fehlermeldung steht leider nichts Näheres dazu …

Das (Desktop)Application.UnhandledException-Event sollte Dir hier weiterhelfen können. Es ist auch zu empfehlen in Teilen Deines Programmes, welche Exceptions auslösen könnten, Try…Catch zu verwenden. Somit kannst Du sehen, wo der Fehler auftritt.

Zeigt Application.UnhandledException an, woher die Exception kommt?

In meinem Program hat jedes Event und jede Methode das hier am Ende:

exception exc
theException = new ErrorException(exc, currentMethodName)

Damit mache ich mir einen StackTrace, so daß ich sehe, wo der Fehler auftritt und welche Methoden den Fehler aufgerufen haben. Dann zeige ich ein Fenster, damit mir die Benutzer Informationen zu einem Problem schicken können.

2 Likes

Moin. Danke für den Tip. Wo schreibe ich den Code hin? Ich habe gerade entdeckt, dass man dem obersten Objekt in der Navigation links (heisst wie das Projekt) einen Event “unhandled exception” hinzufügen kann, ist es das? Und return true, wenn ich nicht möchte, dass die Dialogbox erscheint?

Damit mache ich mir einen StackTrace, so daß ich sehe, wo der Fehler auftritt und welche Methoden den Fehler aufgerufen haben. Dann zeige ich ein Fenster, damit mir die Benutzer Informationen zu einem Problem schicken können.

Ja schon, aber die Kunden an einem Verkaufsautomaten interessiert das nicht so sehr. Ich schreibe aber ein Logfile lokal und in eine MySQL im Web …

Ich würde den Stack Trace gerne irgendwie global abfangen und als Text in das Logfile bzw. in eine exztra Tabelle der Datenbank schreiben. Wie bekomme ich denn diesen String innerhalb des “unhandled exception” -Events?

Sieh Dir mal Stack und StackFrames an: RuntimeException — Xojo documentation .

Es ist schon ziemlich lange her, daß ich einen Blick auf UnhandledException geworfen habe. Da klappte das mit dem Stack nicht.

Wieso sollte der Stack denn nicht gehen bei UnhandledException?

Der Stack Trace wird ja abgefragt, wenn die Exception erzeugt wird und dann nur weiter geschoben.
Und ob du das per “Exception” handler in der Methode abfragst oder später die Exception in UnhandledException bekommst, sollte keinen Unterschied machen.

gerade ausprobiert für Linux 64-bit ARM mit einem Projekt.

Function UnhandledException(error As RuntimeException) Handles UnhandledException as Boolean
  Dim f As FolderItem = SpecialFolder.Desktop.Child("exception.txt")
  Dim t As TextOutputStream = TextOutputStream.Append(f)
  
  t.WriteLine Introspection.GetType(error).name
  t.WriteLine error.Message
  For Each s As String In error.Stack
    t.WriteLine s
  Next
  
  Return True
End Function

und

Sub Pressed() Handles Pressed
  // cause exception
  
  Dim n(1) As Integer
  
  n(5) = 1
End Sub

und das schreibt dann auf den Schreibtisch eine Textdatei mit:

OutOfBoundsException

Window1.Window1.Button1_Pressed%%o<Window1.Window1>o
Delegate.IM_Invoke%%o
AddHandler.Stub.20%%
DesktopApplication._CallFunctionWithExceptionHandling%%op
REALbasic._RuntimeRun
_Main
main

Scheint hier also wunderbar zu gehen.

Herzlichen Dank, werde ich einbauen …

OutOfBounds kommt dann, wenn eine Zahl höher ist als vom Array vorgegeben.
Vielleicht könntest du testweise, wenn du Arrays verwendest, dieses niedriger ansetzen und dann das Projekt laufen lassen, so dass die Fehlermeldung früher erscheint als 1x in 10 Tagen.

Besten Dank, genau so habe ich es gemacht.