Exception handling

from Wikipedia, the free encyclopedia

In computer technology, an exception or exception situation ( English exception or trap) denotes a method for passing information on certain program states - mostly error states - to other program levels for further processing.

Can in a program such as a memory request not be granted, a memory request except triggered. To deal with this problem, a computer program can execute defined algorithms that correct or display the error.

Exceptions have largely replaced the handling of errors using error codes or jump instructions and, in the technical sense, represent a second, optional return value of a method / function.

Structured exception handling

The greatest role in programming is played by the structured exception handling (English structured exception handling , short SEH ), a technique that keeps the code separately for exception handling from the normal application code. For example, instead of checking and reacting to a return value that indicates success for every function call, the function in question can trigger an exception in exceptional situations that contains all the information required for problem detection and treatment.

Since the function causing the problem (or the function that identified the problem) may not be able to handle the error appropriately in its context, the exception is passed back to the calling functions until one of them “catches” the exception. It makes sense to handle the exception at a point in the code in which the consequences of this exception can be foreseen and a corresponding reaction to be implemented sensibly (e.g. repeating user input, program termination ). In addition, sections of code between occurrence and handling of the exception are, at best, free of error-handling routines.

Another advantage of the exceptions over conventional error codes is that an exception cannot be ignored. A programmer could forget to check a return value, but an exception is passed back further and further - in extreme cases until it arrives in the program-starting function and thus, under certain circumstances, radically interrupts the program flow.

Almost all newer programming languages ​​support exception handling, for example Java , C ++ , C # , Python, and Visual Basic .NET .

Various hardware architectures (such as the IA-32 architecture from Intel ) support exception handling at the hardware level by the operating system. With certain invalid operations, software interrupts are triggered, which cause a jump into the privileged operating system kernel. This can then use the exception to terminate the program with an error message or forward the error to a debugger.

Checked exceptions

In the programming language Java is available as a development except the "Checked Exception" (dt about. Checked exception ). This is an exception for which the compiler checks that all places where it can occur are covered by code to catch the exception. The code for catching can be in the same method in which the exception can occur, or in calling methods. In the latter case, the programmer has to declare the exceptions in the method signature.

The basic idea behind the design of Java was that exceptions to which the application code can reasonably react should be executed as checked exceptions. Due to the requirement to handle the exception, robust code should be achieved and missing error handling should already be discovered by the compiler. But there are still exceptions that are not checked exceptions. The convention is to implement such errors as checked exceptions where the caller is expected to react to him and restore a regular program sequence. This includes, for example, network, database or other I / O errors. Opening a file can fail for various reasons (no rights, file not available), and the establishment of a network connection can fail for reasons beyond the control of the program. Unchecked exceptions are used to report various types of program errors (for example, index errors in array indexing). In such cases, it is not advisable to have the application attempt to restore a regular program sequence. The classes of the Java platform themselves largely adhere to this convention.

Critics argue against the checked exceptions that they would worsen the readability of the source code and that, because they do not see any benefit in this functionality, they induce alternative constructs that satisfy the compiler but hardly handle errors. Another objection is that, due to the declaration of exceptions in the method signatures, generally usable auxiliary classes or interfaces, especially as part of design patterns , are often not usable with classes that use checked exceptions. Tunneled checked exceptions are suggested as an alternative solution, but these remove the usefulness of the checked exception. In addition, as part of the method signature, checked exceptions stand in the way of the expandability of interfaces.

Newer specialist literature as well as discussions during the development of programming languages ​​of more recent date tend to reject checked exceptions.

Throwing exceptions

An exception can be raised at any point in the program code. An object of an exception class is almost always created and sent with the keyword throwor raise. With some programming languages ​​(for example C ++) any other data type can be used instead of the exception class.

Catching exceptions

If an exception is not explicitly caught in the program flow, then it is caught by the runtime environment . The exception is displayed as an error message; depending on the type of exception, the application is canceled or continued.

Common exception handling errors are:

  • Exceptions are swallowed without further action. Thus, all information about the actual cause of the error is lost.
  • Exceptions are replaced by a separate (often incorrect) message.

It makes sense to catch exceptions in order to enrich additional information and to trigger again.

Examples

Object Pascal

ObjektA := TObjectA.Create;
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
  FreeAndNil(ObjektA); // dies wird auf jeden Fall ausgeführt
end;

C ++

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

C #

MessageServiceClient client = new MessageServiceClient("httpEndpoint");
Message message = ... // Message erstellen
try
{
   client.AddMessage(message);
}
catch (FaultException fe)
{
   Console.WriteLine(fe.Message);
   client.Abort();
}
catch (CommunicationException ce)
{
   Console.WriteLine(ce.Message);
   client.Abort();
}
catch (TimeoutException)
{
   client.Abort();
}

ISO Modula-2

MODULE BeispielAusnahmebehandlung;
  (* Es gibt vordefinierte und benutzerdefinierte Ausnahmen *)
FROM M2EXCEPTION IMPORT M2Exception, IsM2Exception, M2Exceptions;
  (* Deklarationen etc. *)
  IF SpeicherFehler THEN
    RAISE BenutzerdefinierteAusnahme;
  END;
BEGIN
  (* Hauptprogramm *)
EXCEPT
  (* Ausnahmebehandlung *)
FINALLY
  (* Finalisierung *)
EXCEPT
  (* Sollte bei der Finalisierung etwas schiefgehen *)
END BeispielAusnahmebehandlung.

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

Gambas

' Gibt den Inhalt einer Datei aus

Sub PrintFile(FileName As String)

  Dim hFile As File
  Dim sLig As String

  hFile = Open FileName For Read

  While Not Eof(hFile)
    Line Input #hFile, sLig
    Print sLig
  Wend

Finally ' Wird immer ausgeführt, sogar, wenn ein Fehler aufgetreten ist. Achtung: FINALLY muss vor CATCH kommen!
  Close #hFile

Catch ' Wir nur bei einem Fehler ausgeführt
  Print "Cannot print file "; FileName

End

Java

try {
    // Fehlerträchtige Funktion ausführen
    uncertain_code();
} 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");
}

JavaScript

try {
    // Berechne ...
    rechnen();
    // Fehler generieren
    throw new Error("Fehler, Datei kann nicht gelesen werden");
} catch (e) {
    // Fehlertypen unterscheiden (Achtung: dies hier ist nur eine kleine Auswahl)
    if (e instanceof ReferenceError) {
        console.log(e.message);

    } else if(e instanceof SyntaxError) {
      console.log(e.message);

    } else {
      console.log(e);
    }
}
finally {
    // Wird immer ausgeführt, nachdem der Codeblock in "try" abgearbeitet ist
    weiter();
}

PHP

// Exceptionhandling ab PHP Version 5!
try {

    // Berechne ...

    // Fehlermeldung, Fehlercode
    throw new RuntimeException('Fehlermeldung', 543);

} 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;

} finally {

    // ab PHP 5.5
    // Code, welcher immer ausgeführt wird, auch
    // wenn ein Ausnahmefehler aufgetreten ist

}

python

try:
    result = do_something()
    if result < 0:
        raise ValueError

except ValueError:
    print('catching exception')
    do_something_else()

except Exception as e:
    # Catch the exception in "e" and print it.
    print('exception "{}" in method do_something'.format(e))

else:
    print('method do_something passed')

finally:
    print('always print this finally')

See also Python, Exception Handling section .

Pearl

eval {
    something_fatalse(...);
    1;
} or do {
    warn "Exception: $@";
};
# alternativ/ergänzend kann man auch objektorientierte Exception-Module verwenden

Swift

As of version 2, the Swift programming language from Apple also supports exceptions:

    enum MeinFehlerEnum: Error {
      case fehlerA
      case fehlerB
    }
    enum NochEinFehlerEnum: Error {
      case fehlerC
      case fehlerD
    }

    // Funktion kann Fehler mit "throw" werfen, ist deshalb
    // nach Parameter-Liste mit "throws" gekennzeichnet.
    func ersteBerechnung(zahl1:Int, zahl2:Int) throws -> Int {
      if zahl1 == zahl2 { throw MeinFehlerEnum.fehlerA }
      return zahl1 + zahl2
    }

    // Funktion, die keinen Fehler werfen kann.
    func zweiteBerechnung(zahl1:Int, zahl2:Int) -> Int {
      return zahl1 * zahl2
    }

    do {

        // Die Funktion "ersteBerechnung()" ist eine throwing Funktion,
        // sie muss also mit einem vorangestellten "try" aufgerufen werden.
        let ergebnisEins = try ersteBerechnung(zahl1:3, zahl2:4)

        // Die Funktion "zweiteBerechnung()" ist KEINE throwing Funktion,
        // für ihren Aufruf ist also kein "try" erforderlich.
        let ergebnisZwei = zweiteBerechnung(zahl1:ergebnisEins, zahl2:42)

        print("Berechnungs-Ergebnis: \(ergebnisZwei)")

    }
    catch MeinFehlerEnum.fehlerA {
        print("Fehler A ist aufgetreten")
    }
    catch MeinFehlerEnum.fehlerB {
        print("Fehler B ist aufgetreten")
    }
    catch NochEinFehlerEnum.fehlerC {
        print("Fehler C ist aufgetreten")
    }
    catch { // Default-Catch
        print("Unerwarteter Fehler aufgetreten: \(error)")
    }

Swift 2.0 also introduced the keyword deferthat can be used to define a block with code that is always executed when the current block (e.g. method) is exited, even if this block is exited due to an exception. A deferblock can therefore be used in much the same way as the finallyblock known from other programming languages .

Web links

Individual evidence

  1. Ann Wohlrath: Re: Toward a more “automatic” RMI = compatible with basic RMI phi loso phy  ( page no longer available , search in web archivesInfo: The link was automatically marked as defective. Please check the link according to the instructions and then remove this notice. , archives.java.sun.com, accessed October 9, 2008@1@ 2Template: Dead Link / archives.java.sun.com  
  2. Joshua Bloch: Effective Java . Addison-Wesley, 2001, ISBN 0-201-31005-8 , p. 172 ff.
  3. Bruce Eckel: Does Java need Checked Exceptions? ( Memento of April 5, 2002 in the Internet Archive ) Retrieved October 9, 2008
  4. Java's checked exceptions were a mistake . ( Memento of October 14, 2008 in the Internet Archive ) Rod Waldhoff's weblog, accessed October 9, 2008
  5. ExceptionTunneling c2
  6. ^ Robert C. Martin: Clean Code . Prentice Hall, ISBN 978-0-13-235088-4 , pp. 106 .
  7. Jon Skeet: Why doesn't C # have checked exceptions? In: blogs.msdn.microsoft.com. Microsoft, accessed March 15, 2017 .
  8. Michael Kofler : try / catch in Swift 2 . kofler.info. July 24, 2015. Accessed December 17, 2016.
  9. Swift changelog in the official GitHub repository from Apple ( en ) Apple Inc. November 18, 2016. Retrieved December 19, 2016: “New defer statement. This statement runs cleanup code when the scope is exited, which is particularly useful in conjunction with the new error handling model. "