Ada Exception Handler
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Inhaltsverzeichnis dieser Seite
Ada Exceptions Überblick   
Beispiel: Fehlerlokalisierung mit einem Ada Exception Handler   
Beispiel: Steuerung des Programmflusses mit Exceptions   
Links   
Diskussion Steuerung des Programmflusses   
Diskussion Debugger   
Diskussion Fehlerlokalisierung   

Ada Exceptions Überblick    

Es gibt in Ada die folgenden Standard Exceptions:

Constraint_Error : exception;
Program_Error    : exception;
Storage_Error    : exception;
Tasking_Error    : exception;

Werden vom Sprachstandard vorgegebende Libaries angezogen, so können weitere Exceptions sichtbar werden.

Des weiter können vom Entwickler eigene Exceptions definiert werden.

Buffer_Full : exception;

Diese kann der Entwickler innerhalb seines Programmcodes auslösen:

if (Number_of_Elements = Maximum_Elements) then
   raise Buffer_Full;
end if;

Das Program führt seinen normalen Ablauf nun nicht mehr aus sondern springt zum Ende des Blocks. Wird dort ein Exception Block gefunden, so wird nach einem passenden Exception Handler gesucht, der dann ausgeführt wird.

exception
  when Buffer_Full =>
      Remove_Element_from_Buffer;
end Block;

Ist kein Exception Handler vorhanden, so wird im einhüllenden Block nach einem Excheption Handler gesucht; Weitere Details bitte unter Links nachlesen.

Beispiel: Fehlerlokalisierung mit einem Ada Exception Handler    

Diesen Absatz, bzw. diese Seite habe ich auf Grund einer Diskussion auf der Seite LaufzeitFehler geschrieben. Die Fragestellung dort war wie kann man die Selbstanalysefähigkeit der Software erhöhen. Eine Möglichkeit ist die Verwendung eines Exception Handlers, der alle zu einer Exception vorhandenen Informationen ausgibt. Im Idealfall hat jeder Block einen Exception Handler. Zusätzlich zu den im Beispiel ausgegebenen Informationen, sollten die folgenden Informationen ausgegeben werden, so das der fehlerhafte Block schnell gefunden werden kann.

Angenommen im folgende Ada Programm tritt ein nicht behandelter Fehler auf. In diesem Fall wird der Exception Handler im Hauptprogramm (Big_Software_Project) aufgerufen.

with Ada.Text_Io, 
     Ada.Exceptions, 
     First_Procedure, 
     Second_Procedure;
procedure Big_Software_Project is
   use Ada.Text_Io,
       Ada.Exceptions;
begin
   First_Procedure;
   Second_Procedure;
exception
   when Error: others =>
       Put_Line ( "Error in procedure Big_Software_Project." );
       Put_Line ( "Exception_Name:        " & Ada.Exception.Exception_Name );
       Put_Line ( "Exeption_Message:      " & Ada.Exception );
       Put_Line ( "Exception_Information: " & Ada.Exceptions.Exception_Information );
end Big_Software_Project;

Ist nun kein weiterer Exception Handler so wird als nächster Schritt dann ein äquivalenter Exception Handler in den Unterprogrammen First_Procedure und Second_Procedure eingebaut. Beim nächsten auftreten des Fehlers. ist dann klar in welchem der Unterprogramme der Fehler aufgetreten ist. Über ein so aufgebautes Intervallschachtelunsverfahren kann ein Fehler auch in einem großen Projekt sehr schnell lokalisert werden.

Geht die Entwicklung der Software weiter und tritt ein weiterer Fehler auf so wird dieser Fehler mit der gleichen Methode gesucht. Durch diese Vorgehensweise verbessert man dann bei jedem Auftreten eines Fehlers die Selbstanalysefähigkeit des Programms. -- HermannWacker

Beispiel: Steuerung des Programmflusses mit Exceptions    

with Verwaltung;
procedure Software_Firma is

   Bank_Zahlt_erst_nächstes_Jahr : exception;
   Bank_gibt_keinen_Neuen_Kredit : exception;
   Firma_Pleite                  : exception;

   procedure Chef_zur_Bank_Schicken_und_Neuen_Kredit_Organisieren is separate;
   procedure Mitarbeiter_motivieren is separate;

   use Verwaltung;

begin
   loop

         for Monat in Januar..Dezember
         loop
            begin 
               Mitarbeiter_Konten := Monatsgehalt_Berechnen_und_Auszahlen 
                                         ( Firmen_Konten, Personal_Daten, Monat );
            exception
               when Firmen_Konten_Leer =>
                   Chef_zur_Bank_Schicken_und_Neuen_Kredit_Organisieren;
            end;
         exception
             when others => raise;
         end loop;

         Put_Line ("Wir wünschen allen unseren Kunden ein schönes neues Jahr.");

   exception
      when Bank_Zahlt_erst_nächstes_Jahr =>
           Mitarbeiter_motivieren;

      when Bank_gibt_keinen_Neuen_Kredit =>
         raise Firma_Pleite;
   end loop;

exception
    when others =>
        Put_Line ("Tschüss und Danke für den Fisch.");
end Software_Firma;

Links    

Diskussion Steuerung des Programmflusses    

Eine Firma geht nicht notwendigerweise pleite, wenn eine Bank keinen neuen Kredit gibt. Beispielsweise kann die Firma noch einen alten Kredit laufen haben. Oder genügend Rücklagen haben. Ergo schrottiges Beispiel. -- Gruß, VolkerGlave

Gibt es ein gutes Beispiel? Gibt es ein gutes Beispiel für Programmabbruch bei einer Ausnahmesituation?

Ersteres wird seit längerem auf der Seite EinGutesExceptionBeispiel besprochen (meine Ansicht: Nein). Für letzteres gibt es noch keine Seite (meine Ansicht: Ja). -- vgl

Kannst Du ein gutes Beispiel eines Programmabbruchs geben?

Kann ich versuchen. Hast du einen Vorschlag für 'ne Stelle zum Hinlegen, hier (= Ada) passt es nicht. -- vgl

Da hast Du Recht. Vorschlag: EinGutesExceptionBeispiel/EinGutesProgrammAbbruchBeispiel

Die Diskuss läuft unter völlig verkehrten Voraussetzungen. Das Thema ist Exception Handler und nicht die Frage ob dies eine vollständige Simulation eines Geschäftsablaufes ist. Diesen Anspruch hat das Programm nie erhoben. Das Program zeigt aber deutlich wie verschiedene Exceptions auf unterschiedlichen Ebenen behandelt werden. Werde demnächst noch die einzelnen Schritte genauer beschreiben. Das Programm beendet sich übrigens auf dem vom Programmierer definierten Weg und zwar mit der Hilfe von Exceptions. Dieser Weg wurde bewußt gewählt. -- HermannWacker

Diskussion Debugger    

Nachträgliche Anmerkung Auslöser für diese Seite AdaExceptionHandler war die Frage Selbstanalysefähigkeit der Software auf Seite Laufzeitfehler. Ein Exception Handler ist ein Aspekt der Selbstanalysefähigkeit. Ich finde die Diskussion hier aber trotzdem sehr Intressant und möchte diese Weiterführen. Insbesondere unter dem Aspekt was für Möglichkeiten bieten andere Systeme. --HermannWacker

Aus Diskussion Fehlerlokalisierung

Bin ebenfalls erstaunt, kenne aber Ada nicht. Daher die Frage: Welchen Vorteil hat das gegenüber dem Nicht-Behandeln und der Fehlersuche im Debugger? Im Debugger bekommt man doch den kompletten Aufrufstack der zu der Exception geführt hat frei Haus geliefert. In mit VisualWorks (SpracheSmalltalk) entwickelten Anwendungen wird eine Ausschrift des Stacks ihn in eine Log-Datei geschrieben, die der Anwender der Mängelmeldung an den Entwickler beifügt. Also vergleichbar mit dem, was Volker über Java schreibt. -- SaschaDördelmann

Es gibt Fehler, die man mit einem Debugger nicht finden kann. Insbesonder gibt es Fehler, die nicht auftreten, wenn das Programm mit einer Debugge Option übersetzt hat. Das von mir beschriebend Verfahren arbeitet dann immer noch. VisualWorks und Smalltalk kenne ich nicht. -- HermannWacker

Zu: >> Mit Debuggern oder ähnlichen Tools wünsche ich viel Spaß. (Ich freue mich immer wenn ein Arbeitskollege es mal wieder versucht.) <<

Das klingt so, als würdest du den Debugger gar nicht verwenden. Erinnert mich an C++ Entwickler, die nach einigen Versuchen mit fehlerhaften Debuggern die Flinte in's Korn schmeißen und zur Steinzeitprogrammierung a la Debugausgaben übergehen. ;-) Im Ernst: Keinen Debugger zu verwenden, ist in meinen Augen bedenklich. -- SaschaDördelmann

Seh ich genauso. Faustregel bei mir: Jede selbst programmierte Programmzeile mindestens einmal im Einzelschrittmodus durchlaufen haben, inkl. Werte-Beobachtung. (Bitte nicht rückmelden, dass dadurch nichts bewiesen ist. Das weiß ich auch. Beweisen lässt sich aber in Realität eh kaum was. Außerdem hat sich die Regel für mich bewährt. Glaube ich jedenfalls. :-) -- vgl

Bei Multitasking Systemen und Multiprozessorsystemen gibt es viele Fälle, bei denen die Fehler mit Debuggern nicht zu finden sind, da die Programme im Debugger Modus ein anderes Laufzeitverhalten haben. Bei einfachen seriellen Programmen, die ich selber geschreiben habe ist die Fehlersuche ein kleineres Problem. Bei Ada Programmen werden 99% der Fehler sowieso vom Compiler oder Laufzeitchecker gefunden (-> Ada Exception Handler). Bei Java verwende ich Eclipse als Entwicklungsumgebung, welche während der Übersetzung/bzw. beim Editieren Fehler findet (hat auch noch andere geile Feature -> GUnit ) -- HermannWacker

Deshalb debugged ihr noch oder testet ihr schon?

Diskussion Fehlerlokalisierung    

Ist mir ein Rätsel, was das alles soll. Aus Java kenne ich es so: Tritt eine Exception auf, die unbehandelt bleibt, dann gibt die Java-Laufzeitumgebung "von sich aus" die in der Exception enthaltenen Daten (Name der Exception, Call-Stack, ...) aus. Dafür braucht auch nicht eine Zeile Code geschrieben zu werden. Läuft das in Ada etwa anders ab? Würde eine unbehandelte Exception unbemerkt bleiben? -- VolkerGlave

Der Unterschied ist, dass Ada einen Satz von Standard Exceptions hat die alle fundamentalen Fehler abdecken. Wird also durch 0 dividiert, die Bereichsgrenzen eines Arrays überschritten, oder ist nicht mehr genügend Speicherplatz vorhanden, so wird in Ada grundsätzlich eine Exception ausgelöst. Diese wird dann in der Hierarchy nach oben weiter gereicht, bis diese auf einen Exception Handler trifft. Dadurch bekomme ich jeden Fehler, der zu einem Programmabsturz führt. Wenn kein Exception Handler vorhanden ist, liegen die Fehlermeldungen im Ermessen des Compilerherstellers (Gute Laufzeitsystem geben aber den Namen der Exception aus). Bei dem von mir beschreibenen Verfahren, können die Informationen nach den Bedürfnissen des Entwicklers / Projekts erweitert werden. -- HermannWacker

"Der Unterschied ist, ...": Kein Unterschied, Java hat diese Exceptions ebenfalls. "Wenn kein Exception Handler vorhanden ist, liegen die Fehlermeldungen im Ermessen des Compilerherstellers (...).": Das interessiert mich. Gibt es im Netz Dokumente/Artikel, wo man dazu etwas nachlesen kann? Ist für mich schwer vorstellbar, dass so ein entscheidener Punkt bei der Sprache dem Ermessen anheimgestellt wurde. -- vgl

Der Grund weshalb ich diese Seite geschrieben habe war die Diskussion über LaufzeitFehler. Ein äquivalentes Beispiel in Java würde mich sehr Intressieren und wäre die Basis für eine weitere Diskussion. (auch Beispiele in anderen Programmiersprachen). Aber bitte auf einer seperaten Seite (JavaExceptionHandler?). Mann kann sich ja dann verlinken. Die Links wahren schon vor deinem Eintrag vorhanden.

Danke, die Links hatte ich wohl übersehen. Hab's mir jetzt angesehen. Da steht "If there is no exception handler in a particular scope, then the exception is propagated to the calling scope. If the exception is propagated all the way out to the scope of the environment task, then execution of the program is abandoned; [...].". Eine unbehandelte Exception bleibt also schon mal nicht unbemerkt, die Ausführung des Programmes wird angehalten, schön. Dein obiger "Handler" (sofern ich ihn verstehe) torpediert dies allerdings. -- vgl

Habe noch zwei Links eingefügt. Ansonsten hast du das obrige Beispiel vermutlich noch nicht ganz erfasst. Das Programm beendet sich nach der Ausgabe der Fehlermeldungen sauber. Ohne Core Dump. Im nächsten Schritt kann man den Fehler weiter eingrenzen, in dem man die Selbstanalysefähigkeit des Programmes erhöht. Dies kann dann bei dem nächsten Problem weiter helfen.

"Das Programm beendet sich nach der Ausgabe der Fehlermeldungen sauber.": Wie kommt es dazu? Ich sehe keine Anweisung zur Programmbeendigung. -- vgl

Der Exceptionhandler ist das letzte Stück Code in dem Programm, danach kommt nur noch das Ende (Vermutung eines Ada-Ignoranten)

Das stimmt insofern, als Big_Software_Project oben als Hauptprogramm definiert ist, ja. Aber der Autor sagt dann weiter "Als nächster Schritt wird dann ein äquivalenter Exception Handler in den Unterprogrammen First_Procedure und Second_Procedure eingebaut. [...]". Nach Unterprogrammaufrufen kommt sehr wohl noch was anderes als das Ende. Ich halte meine Frage also aufrecht: Wie kommt es zur Beendigung des Programms, ich sehe keine Anweisung zur Programmbeendigung? -/- Die Intervallschachtelungsstrategie finde ich zwar seltsam (wie gesehen in Java und Smalltalk überflüssig), aber von mir aus. Ist es dann aber so, dass diese Fehleraufdeckungs-Exceptionhandler im Produktionscode wieder vollständig entfernt werden? Sonst können in Produktion ja tatsächlich unbedachte Ausnahmen ignoriert werden (es sei denn, das Programm wird beendet, was ich aber wie gesagt bislang nicht sehe). -- vgl

Mal der Versuch einer Kurzübersetzung nach Java. Jeder Ada Block (Begin ... end) stellt ein try da. Ein try ist also grundsätzlich vorhanden und muß nicht explizit hingeschrieben werden. Eine exception Block entspricht einem catch und ein raise statement einem throw. Desweiteren kann ich in Ada jede parameterlose procedure als Hauptprogram verwenden. Wird in einem Block eine exception ge'raised' so bedeutet dies das die normale Weiterführung dieses Blocks nichtmehr möglich ist. Die Ausführung springt also in den Exception Block und sucht nach einem passenden Exception Handler um diesen Auszuführen. Ist in dem Block kein Exception Handler so wird im umgebenden Block einer gesucht. Ist im Hauptprogramm kein Handler so beendet sich das Programm mit einer Fehlermeldung. Im Obrigen Beispiel ist im Hauptprogramm ein Exceptionhandler eingebaut der alle Exceptions abfängt (when other=>) und alle zu dieser Execption vorhandenen Informationen ausgibt (Put_Line). Danach beendet sich das Programm ohne weitere Fehlermeldung.

Der Ausgangspunkt der Diskussion war Selbstanalysfähigkeit der Software in LaufzeitFehler nicht wie finde ich Fehler mit der Hilfe meiner Akuten Entwicklungsumgebung. Diese ändert sich aber von Projekt zu Projekt mit schwankender Qualität und unterschiedlicher Dicke der Debugger Manuals. Also stellt sich die Frage wie finde ich Fehler unabhänging von meiner konkreten Entwicklungsumgebung.

Zur Intervallschachtellung: Angenommen man hat ein Programm mit 1024 Unterprogrammen die jeweils aus 1024 Statements bestehen. Also eine gute Millionen Lines of Code. Mit dem Intervallschachtelungsverfahren hat man die den Fehler auslösende Zeile nach genau 20 Iterationen gefunden. Mit Debuggern oder ähnlichen Tools wünsche ich viel Spaß. (Ich freue mich immer wenn ein Arbeitskollege es mal wieder versucht.)

Ok, das im ersten Abschnitt (Übersetzung nach Java) hatte ich so vermutet. Von wegen "mit Debuggern oder ähnlichen Tools wünsche ich viel Spaß" kann ich erstmal nur wiederholen, dass in Java der ganz Aufwand, den du treibst, überflüssig ist, weil auftretende Exceptions, die unbehandelt sind, in ziemlicher Ausführlichkeit (u. a. Exception-Name und Call-Stack) auf den Standardfehlerkanal ausgegeben werden, und zwar ohne Debugger oder Tools. Anscheinend ist Ada in dieser Hinsicht unausgereift. (Die Ausgabe erfolgt allerdings nicht, wenn unfähige Programmierer Exceptions, die sie eigtl. nichts anzugehen haben, fälschlicherweise wegfangen. Eine leider häufig anzutreffende Unart, und eine, die mit obiger von dir aufgezeigter Strategie verdächtige Ähnlichkeit aufweist.) -/- Meine Frage, ob bzw. wie sich das Programm beendet, wenn der vor dir vorgeschlagene Handler _nicht_ in der Hauptroutine steht, ist immer noch nicht beantwortet. Auch ist nicht beantwortet, ob ihr die zur Auffindung eingefügten Handler (die nicht wirklich handeln, sondern nur Output generieren) in Produktionscode wieder herausnehmt. Im übrigen kauft dir niemand das "nach genau 20 Iterationen" ab, weil Fehler (gerade die schwierigen) oft nicht ohne weiteres reproduzierbar sind. -- vgl

Der normale Ablauf des Programmes ist ganz einfach First_Procedure und Second_Procedure werden nacheinander augeführt und danach beendet sich das Programm. Der Unterschieht zwischen Java und Ada ist, daß Java nur eine VM kennt. Ada erfordert eine Betriebsystem sprezifische Compilierung. Entsprechend sind die Debuggwerkzeuge unterschiedlich. Der Exception Mechanismus ist aber Einheitlich. Desweiteren erfordert ein Ada Compiler, wenn er sich wirklich Ada nennen will eine Validierung. Was dazu führt, das Ada Code hoch Portable ist. Hat von daher auf Sourcecode Level ähnliche Eigenschaften wie Java.

"Der normale Ablauf des Programmes ist ganz einfach First_Procedure und Second_Procedure werden nacheinander augeführt und danach beendet sich das Programm.": Wenn also in First_Procedure eine unerwartete Exception passiert, die du nach deinem Intervallschachtelungsverfahren nun in den Output gibst, wird danach trotzdem (also trotz, dass sich das Programm in einem unerwarteten Zustand befindet) noch regulär Second_Procedure ausgeführt. Nicht gut. -- vgl

Ob Second_Procedure ausgeführt werden soll liegt im Ermessen des Entwicklers. Er kann in First_Procedure im Fehlerfall die Ausgabe erzeugen und sich dann entscheiden ob er die Exception weiter propagiert oder die Procedure normal beendet. Die Weiterleitung sieht wie folgt aus:
exception
   when others =>
      Put_Line ( "Hier ist was schiefgelaufen." );
      raise;
Normal beenden wird sich die Procedure in der folgenden Form:
exception
   when others =>
       Put_Line ( "Hier ist was schiefgelaufen." );

Variante #1 ist ok. (Noch besser gefiele mir Programmabbruch statt 'raise', wozu ich in einer Paralleldiskussion allerdings noch Material liefern muss ...) -- vgl

Welche Variante man wählt hängt davon ab was man machen will in der ersten Variante wird die Exception in der Hierarchie nach oben weiter gereicht. Im Prinzip kann man so die gesamte Aufrufhierarchy durchlaufen und entsprechende Ausgaben erziehlen. In der Zweiten Variante bekommet man nur die Informationen des lokalen Exception Handlers. Die Ausgaben sind bedeutend übersichtlicher. Welche Variante man wählt hängt von der konkreten Situation ab und läßt sich allgemein nicht entscheiden.

Doch, das lässt sich allgemein entscheiden. Wer eine Behandlung unerwarteter Exceptions in eine Prozedur einbaut ("when others =>"), und zwar eine Behandlung, die zwecks Analyse für die weitere Programmentwicklung nichts weiter tut als die unerwartete Exception in lesbarer Form auf den Standardausgabekanal auszugeben, und wer dann _trotzdem_ sein Programm regulär weiterlaufen lässt, der erklärt damit die zuvor unerwartete Exception im Nachhinein zur erwarteten Exception, und der widerspricht sich damit selbst. Niemand, der seine Sinne beisammen hat, lässt ein Programm weiterlaufen, dass erkanntermaßen unerwartetes Verhalten gezeigt hat, weil alle folgenden Ergebnisse des Programmlaufs zwangsläufig wertlos sind (weil man nicht wissen kann, ob das unerwartete Verhalten sie schadhaft beinflusst hat). Deshalb führen unbehandelte Exceptions bei normalen Programmiersprachen (C++, Java) zur Beendigung des Programms. Und deshalb ist Variante #1 richtig. (Noch richtiger ist m. M. n. sofortiger Abbruch, doch dazu später mehr in diesem Theater ...) -- vgl

Wenn mit dem Programm das ganze Flugzeug abstürzt sollte man sich das doch noch mal überlegen.

Es ist überlegt. Ein Programm, in dem ein unerwartetes Ereignis aufgetreten ist, abzuschalten, ist sinnvoller, als es weiter (nämlich: Amok) laufen zu lassen. -- vgl

Wenn man es unter dem Gesichtspunkt der Fehlerlokalisierung sieht, stellt sich die Frage ob ich die Information nur über die Procedure haben will oder ob man die Information über die Aufrufhierarchie braucht. Entsprechend gestaltet man den Exception Handler.


KategorieProgrammierBeispiele KategorieException
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 27. Juni 2005 21:18 (diff))
Suchbegriff: gesucht wird
im Titel
im Text