Ausnahme (EDV)

Ausnahme (EDV)
Klassifizierung verschiedener Ausnahmesituationen

Eine Ausnahme oder Ausnahmesituation (engl. exception) bezeichnet in der Computertechnik ein Verfahren, Informationen über bestimmte Programmzustände – meistens Fehlerzustände – an andere Programmebenen zur Weiterbehandlung weiterzureichen.

Kann in einem Programm beispielsweise einer Speicheranforderung nicht stattgegeben werden, wird eine Speicheranforderungs-Ausnahme ausgelöst. Ein Computerprogramm kann zur Behandlung dieses Problems dafür definierte Algorithmen abarbeiten, die den Fehler ignorieren, beheben oder anzeigen.

Sachgemäße Anwendung von Ausnahmen ermöglicht es Programmen, flexibler auf unvorhergesehene Probleme zu reagieren und sich fehlertoleranter zu verhalten.

Inhaltsverzeichnis

Strukturierte Ausnahmebehandlung

Die größte Rolle in der Programmierung spielt dabei die strukturierte Ausnahmebehandlung (englisch structured exception handling, kurz SEH), eine Technik, die den Code zur Ausnahmebehandlung vom normalen Anwendungscode getrennt hält. Anstatt beispielsweise bei jedem Funktionsaufruf einen Rückgabewert, der den Erfolg anzeigt, zu prüfen und darauf zu reagieren, kann man die betreffende Funktion in Ausnahmesituationen eine Ausnahme auslösen lassen, die alle für die Problemerkennung und -behandlung erforderlichen Informationen in sich trägt.

Da die verursachende Funktion (oder die Funktion, die das Problem feststellt) in ihrem Kontext den Fehler möglicherweise nicht angemessen behandeln kann, wird die Exception so lange an aufrufende Funktionen zurückgereicht, bis schließlich eine die Exception „fängt“. Dies baut man sinnvollerweise an einer Stelle im Code ein, wo abzusehen ist, was für Konsequenzen diese Ausnahme haben kann und wie man darauf am besten reagiert (zum Beispiel neue Benutzereingabe, Programmabbruch, Abbruch einer bestimmten Operation). Außerdem ist jeder Code-Abschnitt, der bezüglich der Ausnahmebehandlung nichts ausrichten kann, frei von Fehlerbehandlungsroutinen.

Ein weiterer entscheidender Vorteil gegenüber der Fehlerbehandlung über Rückgabewerte ist, dass eine Exception nicht ignoriert werden kann. Ein Programmierer könnte vergessen, einen Rückgabewert zu prüfen, aber eine Exception wird immer weiter zurückgereicht, bis sie in der Programmstartenden Funktion ankommt, falls der Programmierer es unterlassen hat, sie abzufangen. In diesem Fall führt das oft zu einem Programmabbruch. Dies mag etwas subtil erscheinen, das Resultat ist jedoch meistens, dass Programme, die trotz Fehlerbehandlung per Exceptions stabil laufen, auch wirklich stabil laufen. Demgegenüber kann das Ignorieren eines Fehlerwertes viele Male keine drastischen Konsequenzen haben und irgendwann könnte das Programm eventuell doch unerwartete Ergebnisse produzieren.

Programmiersprachen, die Ausnahmebehandlung unterstützen, sind zum Beispiel C++, Delphi, Java, C#, Python, PHP (ab Version 5), Ruby, Eiffel, Ada, Objective CAML und Visual Basic .Net.

Verschiedene Hardware-Architekturen (wie zum Beispiel die IA-32-Architektur von Intel) unterstützen eine Exception-Behandlung auf Hardware-Ebene durch das Betriebssystem. Hierbei werden bei bestimmten ungültigen Operationen Software-Interrupts ausgelöst, die einen Einsprung in den privilegierten Betriebssystemkern verursachen. Dieser kann dann anhand der Exception das Programm mit einer Fehlermeldung beenden oder den Fehler an einen Debugger weiterleiten.

Checked Exceptions

Bei Java gibt es als Weiterentwicklung der Ausnahme die „Checked Exception“ (dt. etwa: überprüfte Ausnahme). Das ist eine Ausnahme, bei der der Compiler prüft, ob alle Stellen, wo sie auftreten kann, durch Code zum Abfangen der Ausnahme abgedeckt sind. Der Code zum Abfangen kann dabei innerhalb derselben Methode stehen, in der die Ausnahme auftreten kann, oder auch in aufrufenden Methoden. In letzterem Fall muss der Programmierer die Ausnahmen in der Methodensignatur deklarieren.

Die zugrunde liegende Idee beim Entwurf von Java war, dass Ausnahmen, auf die der Anwendungscode sinnvoll reagieren kann, als Checked Exception ausgeführt werden. Durch den Zwang zur Behandlung der Ausnahme sollte robuster Code erreicht werden und fehlende Fehlerbehandlungen bereits vom Compiler entdeckt werden.[1] Es gibt aber weiterhin Ausnahmen, die keine Checked Exceptions sind. Als Konvention gilt dabei, solche Fehler als Checked Exception zu realisieren, bei denen man vom Aufrufer erwartet, dass er auf ihn reagieren und einen geregelten Programmablauf wiederherstellen kann. Darunter fallen beispielsweise Netzwerk-, Datenbank- oder sonstige E/A-Fehler. So kann das Öffnen einer Datei aus verschiedenen Gründen fehlschlagen (keine Rechte, Datei nicht vorhanden), der Aufbau einer Netzwerkverbindung kann aus vom Programm nicht zu beeinflussenden Gründen fehlschlagen. Nicht-Checked-Exceptions sind zum Melden verschiedener Arten von Programmfehlern vorgesehen (zum Beispiel Indexfehler bei Array-Indizierung). Es wird davon abgeraten, die Anwendung in solchen Fällen versuchen zu lassen, einen geregelten Programmablauf wiederherzustellen.[2] Die Klassen der Java-Plattform selber halten sich weitgehend an diese Konvention.

Kritiker führen gegen die Checked Exceptions an, dass sie die Lesbarkeit des Quellcodes verschlechtern würden und dass sie viele Programmierer, weil sie in dieser Funktionalität keinen dem Aufwand entsprechenden Nutzen erkennen, zu Ausweichkonstrukten verleiten, die dem Compiler genügen, aber kaum Fehler behandeln.[3] Ein anderer Einwand ist, dass aufgrund der Deklaration der Exceptions in den Methodensignaturen allgemein verwendbare Hilfsklassen oder Interfaces, insbesondere als Teil von Entwurfsmustern, oft nicht sinnvoll operabel sind mit Klassen, die Checked Exceptions verwenden.[4] Als Ausweichlösung werden getunnelte Checked Exceptions vorgeschlagen, die aber den Nutzen der Checked Exception aufheben.[5]

Auslösen von Exceptions

Eine Exception kann an jeder Stelle im Programmcode ausgelöst werden. Dabei wird fast immer ein Objekt einer Exception-Klasse erzeugt und mit dem Schlüsselwort throw oder raise abgeschickt. Bei manchen Programmiersprachen (zum Beispiel C++) darf statt der Exception-Klasse auch jeder andere Datentyp verwendet werden.

Abfangen von Exceptions

Wird eine Exception im Programmablauf nicht explizit abgefangen, dann wird sie von der Laufzeitbibliothek aufgefangen. Die Exception wird als Fehlermeldung angezeigt; je nach Art der Exception wird die Anwendung abgebrochen oder fortgesetzt. Anwendungen ohne eigene Benutzeroberfläche werden immer abgebrochen.

Häufige Fehler bei der Ausnahmebehandlung sind

  • Exceptions werden ohne weitere Aktionen geschluckt. Somit geht die eigentliche Fehlerursache verloren.
  • Exceptions werden durch eine eigene (häufig unzutreffende) Meldung ersetzt.

Es ist sinnvoll, Exceptions abzufangen, um zusätzliche Informationen anzureichern und erneut auszulösen.

Beispiele

Borland Delphi

ErstelleObjektA;
try
  try
    BerechneEinkommen(name);
  except
    on E:Exception do
    begin
      // Exception wurde abgefangen und wird um einen aussagekräftigen Hinweis ergänzt
      E.Message := 'Fehler beim Berechnen des Einkommens von '+name+#13#10+
        E.Message; // ursprüngliche Meldung anhängen
      Raise;  // veränderte Exception erneut auslösen
    end;
  end;
finally
  EntferneObjektA; //dies wird auf jeden Fall ausgeführt
end;

C++

try {
  funktion1();
  funktion2();
   ...
} catch (std::invalid_argument &e) {
  std::cerr << "Falsches Argument:"  << e.what() << std::endl;
} catch (std::range_error &e) {
  std::cerr << "Ungültiger Bereich:" << e.what() << std::endl;
} catch (...) {
  std::cerr << "Sonstige Exception" << std::endl;
}

C#

try
{
  TryToDoSomething(23, 42);
}
catch (Exception ex)
{
  // Fehler behandeln.
  System.Console.WriteLine("Ausnahme aufgetreten: %s", ex.Message);
}
finally
{
  // Wird auf jeden Fall ausgeführt.
  System.Console.WriteLine("Versuch durchgeführt.");
}

Visual Basic .NET

' Versuche ... 
Try
  ' ... die Methode oder Prozedur ...
  BerechneEinkommen(name)
' bei Ausnahme
Catch ex AS Exception
  ' gib Ausnahme aus
  MessageBox.Show("Fehler -> " & ex.message)
' Führe auf jeden Fall aus
Finally
  MessageBox.Show("Das wird trotzdem ausgeführt")
End Try

Java

try {
    //Berechne ...
} catch (OutOfMemoryError e) {
    //Ein Error ist keine Exception und muss separat abgefangen werden
    e.printStackTrace();
} catch (RuntimeException e) {
    //z.B. IndexOutOfBoundsException, NullPointerException usw.
    System.err.println("Offensichtlich ein Programmierfehler!");
    throw e; //Leite nach oben weiter
} catch (Exception e) {
    //Fange alle restlichen Ausnahmefehler ab
    e.printStackTrace();      
} catch (Throwable t) {
    //Das hier fängt wirklich alles ab
    t.printStackTrace();
} finally {
    //Ob Exception oder nicht, führe das hier auf jeden Fall aus.
    System.out.println("Berechnung beendet oder abgebrochen");
}

PHP

//Exceptionhandling ab PHP Version 5!
try {
    //Berechne ...
    throw new RuntimeException('Fehlermeldung',543); //Fehlermeldung, Fehlercode
} catch (RuntimeException $e) {
    //z.B. IndexOutOfBoundsException, NullPointerException usw.
    //Wichtig: Um die hier verwendeten Basistypen zu nutzen muss die "SPL" installiert sein 
    echo($e->getMessage());
    throw $e; //Leite nach oben weiter
} catch (Exception $e) {
    //Fange alle restlichen Ausnahmefehler ab und verwende die __toString() - Methode zur Ausgabe
    echo($e);
}

Python

try:
    result = doSomething()
    if result < 0 :
        raise StandardError
 
except StandardError:
    print("catching exception")
    doSomethingElse()
 
except :
    print("exception in method doSomething")

siehe auch Python Ausnamebehandlungen

Stacktrace

Der Stacktrace kann insbesondere für eine manuelle Sichtung der Situation bei Auftreten einer Ausnahme wertvoll sein, um insbesondere bei nicht aufgefangenen Ausnahmen die Ursache schnell erkennen und beheben zu können. Der Stacktrace, das ist die Aufrufreihenfolge aller Methoden bis zur Ausnahme, kann beispielsweise in ein Log-System ausgegeben werden und auf diese Weise einem Entwicklerteam zur Verfügung stehen, auch wenn eine nicht behandelte Ausnahme in einer Software beim Kunden auftritt. In Java ist das Exceptionhandling unmittelbar mit dem Stacktrace verbunden.

Technische Umsetzung

In nativ compilierten Sprachen wie C++ wird meistens Code generiert, der zur Laufzeit Informationen zur Ausnahmebehandlung protokolliert. In C++ werden „abgesicherte“ Bereiche von einem try-Block umfasst. Jeder Eintritt in und Austritt aus einem try-Block wird auf einer dafür vorgesehenen Datenstruktur (meistens ein Stack) notiert. Wird eine Ausnahme ausgelöst, kann diese Datenstruktur nach einer passenden Fehlerbehandlung durchsucht werden und der Kontrollfluss so lange aufgerufene Funktionen verlassen, bis er den ausgewählten Handler erreicht.

Bei vielen Virtuellen Maschinen wie zum Beispiel JVM oder .NET kann auf den Overhead des ständigen Protokollierens verzichtet werden, da der Bytecode bei Auftreten einer Ausnahme nach einem passenden Handler abgesucht werden kann. Somit verursachen nur noch tatsächlich ausgelöste Ausnahmen Overhead und nicht mehr jede mögliche.

Weblinks

Einzelnachweise

  1. Ann Wohlrath: Re: Toward a more "automatic" RMI = compatible with basic RMI phi loso phy, archives.java.sun.com, abgerufen 9. Oktober 2008
  2. Joshua Bloch: Effective Java, Addison-Wesley, 2001, ISBN 0-201-31005-8, S. 172 ff.
  3. Bruce Eckel: Does Java need Checked Exceptions?, abgerufen 9. Oktober 2008
  4. Java's checked exceptions were a mistake, Rod Waldhoff's Weblog, abgerufen 9. Oktober 2008
  5. c2:ExceptionTunneling

Wikimedia Foundation.

Игры ⚽ Поможем сделать НИР

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Null (EDV) — Dieser Artikel behandelt den Betriff des Nullwerts aus der EDV; zu weiteren Bedeutungen von Null siehe 0. Als Nullwert (kurz NULL, NIL oder ()) bezeichnet man in der Informatik einen Zustand, der das Fehlen eines Wertes anzeigen soll. Nach Edgar… …   Deutsch Wikipedia

  • JFC — Java Objektorientierte Programmiersprache Basisdaten Paradigmen: Objektorientierte Programmiersprache Aktuelle  …   Deutsch Wikipedia

  • Java (Framework) — Java Objektorientierte Programmiersprache Basisdaten Paradigmen: Objektorientierte Programmiersprache Aktuelle  …   Deutsch Wikipedia

  • Java (Softwaretechnologie) — Java Objektorientierte Programmiersprache Basisdaten Paradigmen: Objektorientierte Programmiersprache Aktuelle  …   Deutsch Wikipedia

  • Programmiersprache Java — Java Objektorientierte Programmiersprache Basisdaten Paradigmen: Objektorientierte Programmiersprache Aktuelle  …   Deutsch Wikipedia

  • Entfernter Methodenaufruf — Remote Method Invocation (RMI, deutsch etwa „Aufruf entfernter Methoden“), gelegentlich auch als Methodenfernaufruf bezeichnet, ist der Aufruf einer Methode eines entfernten Java Objekts und realisiert die Java eigene Art des Remote Procedure… …   Deutsch Wikipedia

  • Programmiersprache Cluster — Die Programmiersprache Cluster wurde Anfang der 1990er von Thomas Pfrengle und Ulrich Sigmund (StoneWare) für das Amiga Graphikkartensystem EGS entwickelt. Sie ist ein Dialekt der Programmiersprache Modula 2 mit Anleihen aus Oberon… …   Deutsch Wikipedia

  • Liste der in Deutschland vorhandenen Dampflokomotiven — Diese Liste der in Deutschland vorhandenen Dampflokomotiven erhebt keinen Anspruch auf Vollständigkeit. Auch wenn von einigen Baureihen noch viele Exemplare vorhanden sind, sollte dies nicht über den teilweise sehr schlechten Zustand täuschen. Es …   Deutsch Wikipedia

  • Liste in Deutschland vorhandener Dampflokomotiven — Diese Liste der in Deutschland vorhandenen Dampflokomotiven erhebt keinen Anspruch auf Vollständigkeit. Auch wenn von einigen Baureihen noch viele Exemplare vorhanden sind, sollte dies nicht über den teilweise sehr schlechten Zustand vieler… …   Deutsch Wikipedia

  • Grundbuch — Das Grundbuch ist ein amtliches öffentliches Verzeichnis von Grundstücken, in dem die Eigentumsverhältnisse sowie etwaige mit dem Grundstück verbundene Rechte und auf ihm liegende Lasten erfasst werden. Inhaltsverzeichnis 1 Geschichte 1.1 Antike… …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”