Exception handling syntax

This is an old revision of this page, as edited by 82.41.186.154 (talk) at 16:00, 7 January 2007 ([[Ada (programming language)|Ada]]). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Exception handling syntax varies between programming languages to accommodate their overall syntax. Some languages don't call the concept exception handling or they may not have direct facilities for it, but they can still provide means for implementing it.

Catalogue of exception handling syntaxes

Exception declarations

Exceptions are declared rather like objects, but they are not objects. For example, recursive re-entry to a scope where an exception is declared does not create a new exception of the same name; instead the exception declared in the outer invocation is reused.

Ex.1

  Line_Failed : Template:Ada/kw;

Ex.2

  Template:Ada/kw Directory_Enquiries Template:Ada/kw

     Template:Ada/kw Insert (New_Name   : Template:Ada/kw Name;
                       New_Number : Template:Ada/kw Number);

     Template:Ada/kw Lookup (Given_Name  : Template:Ada/kw  Name;
                       Corr_Number : Template:Ada/kw Number);

     Name_Duplicated : Template:Ada/kw;
     Name_Absent     : Template:Ada/kw;
     Directory_Full  : Template:Ada/kw;

  Template:Ada/kw Directory_Enquiries;

Raising exceptions

The raise statement explicitly raises a specified exception.

Ex. 1

  Template:Ada/kw Template:Ada/kw Directory_Enquiries Template:Ada/kw
  
     Template:Ada/kw Insert (New_Name   : Template:Ada/kw Name;
                       New_Number : Template:Ada/kw Number)
     Template:Ada/kwTemplate:Ada/kwTemplate:Ada/kw New_Name = Old_Entry.A_Name Template:Ada/kw
           Template:Ada/kw Name_Duplicated;
        Template:Ada/kw Template:Ada/kw;
        …
        New_Entry :=  Template:Ada/kw Dir_Node'(New_Name, New_Number,…);
        …
     Template:Ada/kw
        Template:Ada/kw Storage_Error => Template:Ada/kw Directory_Full;
     Template:Ada/kw Insert;
     
     Template:Ada/kw Lookup (Given_Name  : Template:Ada/kw  Name;
                       Corr_Number : Template:Ada/kw Number)
     Template:Ada/kwTemplate:Ada/kwTemplate:Ada/kw Template:Ada/kw Found Template:Ada/kw
           Template:Ada/kw Name_Absent;
        Template:Ada/kw Template:Ada/kw;
        …
     Template:Ada/kw Lookup;
  
  Template:Ada/kw Directory_Enquiries;

Exception handling and propagation

Exception handlers may be grouped at the end of a block, subprogram body, etc. A handler is any sequence of statements that may end:

  • by completing;
  • by executing a return statement;
  • by raising a different exception (raise e;);
  • by re-raising the same exception (raise;).

Suppose that an exception e is raised in a sequence of statements U (a block, subprogram body, etc.).

  • If U contains a handler for e: that handler is executed, then control leaves U.
  • If U contains no handler for e: e is propagated out of U; in effect, e is raised at the "point of call” of U.

So the raising of an exception causes the sequence of statements responsible to be abandoned at the point of occurrence of the exception. It is not, and cannot be, resumed.

Ex. 1

  ...
  Template:Ada/kw
     Template:Ada/kw Line_Failed =>
        Template:Ada/kw Template:Ada/--
           Log_Error;
           Retransmit (Current_Packet);
        Template:Ada/kw
           Template:Ada/kw Line_Failed =>
              Notify_Engineer; Template:Ada/--
              Abandon_Call;
        Template:Ada/kw;
  ...

Information about an exception occurrence

Ada provides information about an exception in an object of type Exception_Occurrence, defined in Template:Ada/package along with subprograms taking this type as parameter:

  • Exception_Name: return the full exception name using the dot notation and in uppercase letters. For example, Queue.Overflow.
  • Exception_Message: return the exception message associated with the occurrence.
  • Exception_Information: return a string including the exception name and the associated exception message.

For getting an exception occurrence object the following syntax is used:

Template:Ada/kw Template:Ada/package 2;  Template:Ada/kw Template:Ada/package 2;
...
Template:Ada/kw
  Template:Ada/kw Error: High_Pressure | High_Temperature =>
    Put ("Exception: ");
    Put_Line (Exception_Name (Error));
    Put (Exception_Message (Error));
  Template:Ada/kw Error: Template:Ada/kw =>
    Put ("Unexpected exception: ");
    Put_Line (Exception_Information(Error));
Template:Ada/kw;

The exception message content is implementation defined when it is not set by the user who raises the exception. It usually contains a reason for the exception and the raising ___location.

The user can specify a message using the procedure Raise_Exception.

Template:Ada/kw
   Valve_Failure : Template:Ada/kw;
Template:Ada/kw
  ...
  Raise_Exception (Valve_Failure'Template:Ada/attribute, "Failure while opening");
  ...
  Raise_Exception (Valve_Failure'Template:Ada/attribute, "Failure while closing");
  ...
Template:Ada/kw
  Template:Ada/kw Fail: Valve_Failure =>
    Put (Exceptions_Message (Fail));
Template:Ada/kw;

The package also provides subprograms for saving exception occurrences and reraising them.

For a more complete discussion of exceptions in Ada see the wikibook on Ada.

ON ERROR GOTO handler
OPEN "Somefile.txt" FOR INPUT AS #1
CLOSE #1
PRINT "File opened successfully"
END
handler:
PRINT "File does not exist"
END
public static void Main()
{
   try
   {
      // Code that could throw an exception
   }
   catch(System.Net.WebException exp)
   {
      //Process a WebException
   }
   catch(System.Exception)
   {
      //Process a System level CLR exception, that is not a System.Net.WebException
      //since the exception has not been given an identifier it cannot be referenced
   }
   catch
   {
      //Process a non-CLR exception
   }
   finally
   {
      // (optional) code that will *always* execute
   }
}
#include <exception>
int main() {
   try {
       // do something (might throw an exception)
   }
   catch (const std::exception& e) {
        // handle exception e
   }
   catch (...) {
        // unknown exception, should not happen
   }
}

In C++, a resource acquisition is initialization technique can be used to clean up resources in exceptional situations.

 import std.stdio; // for writefln()
 int main() {
   try {
       // do something that might throw an exception
   }
   catch (FooException e) {
        // handle exceptions of type FooException
   }
   catch (Object o) {
        // handle any other exceptions
        writefln("Unhandled exception: ", o);
        return 1;
   }
   return 0;
}

In D, a finally clause or the resource acquisition is initialization technique can be used to clean up resources in exceptional situations.

try {
   // Normal execution path
} catch (ExampleException ee) {
   //  deal with the ExampleException
} finally {
   // This optional section is executed upon termination of any of the try or catch blocks above
}
begin
  # Do something nifty
  raise SomeError, "This is the error message!"  # Uh-oh!
rescue SomeError
  # This is executed when a SomeError exception
  # is raised
rescue AnotherError => error
  # Here, the exception object is referenced from the
  # `error' variable
else
  # This is executed only if no exceptions were raised
ensure
  # This is always executed, exception or not
end
try:
   f = file("aFileName")
except IOError:
   print "Unable to open file"
except:  # catch all exceptions
   print "Unexpected error"
else:    # no exception was raised
   try:
       f.write(could_make_error())
   finally:  # clean-up actions
       f.close()
exception MyException of string * int (* exceptions can carry a value *)
let _ =
  try
    raise (MyException ("not enough food", 2));
    print_endline "Not reached"
  with
  | MyException (s, i) -> 
      Printf.printf "MyException: %s, %d\n" s i
  | _ ->  (* catch all exceptions *)
      print_endline "Unexpected exception"

The most common way to implement exception handling in standard C is to use setjmp/longjmp functions:

#include <setjmp.h>
#include <stdio.h>
enum { SOME_EXCEPTION = 1 };
jmp_buf state;
int main()
{
  int exception;
  if((exception = setjmp(state)) == 0)  // try
  {
    if(/* something happened */)
      longjmp(state, SOME_EXCEPTION);   // throw SOME_EXCEPTION
  } 
  else switch(exception)
  {             
    case SOME_EXCEPTION:                  // catch SOME_EXCEPTION
      puts("SOME_EXCEPTION caught");
      break;
    default:                              // catch ...
      puts("Some strange exception");
  }
  return 0;
}

Some operating systems also have similar features, for example Microsoft Windows has "Structured Exception Handling" (SEH):

int filterExpression (EXCEPTION_POINTERS* ep) {
   ++ep->ContextRecord->Eip;
   return EXCEPTION_CONTINUE_EXECUTION;
}
int main() {
   static int zero;
   __try {
       zero = 1/zero;
       printf ("Past the exception.\n");
   } __except (filterExpression (GetExceptionInformation())) {
       printf ("Handler called.\n");
   }
   return 0;
}
eval {
    # Code that could throw an exception
}
if($@){
    # Handle exception here. (The exception object is in $@)
}
// Exception handling is only available in PHP versions 5 and greater.

== try ==

try
{
... // Code which might throw an exception
}
catch (FirstExceptionClass $exception) 
{
... // Code which handles this exception
} 
catch (SecondExceptionClass $exception) 
{
  // you get the idea what i mean ;)
}

(php5powerprogramming: ISBN 0-13-147149-X, page 77)

try
  try
    // Code which may raise an exception
  except
    on E:Exception do
    // Code to call when an exception is raised
  end;
finally
  // Code which will be executed whether or not an exception is raised (e.g. clean-up code)
end;
try for 30 minutes
     cd /tmp
     rm -f data
     forany host in xxx yyy zzz
           wget http://${host}/fresh.data data
     end
end

See also