9. Ausnahmen und Ausnahmebehandlung
 
zurück
9.3 Vordefinierte Ausnahmen


In Ada existieren folgende vordefinierte Ausnahmen:

Constraint_Error - wird ausgelöst, wenn Bereichseinschränkungen, Indexeinschränkungen oder Diskriminaten-einschränkungen verletzt werden. Numeric_Error - ist aus Kompatibilitätsgründen zu Ada 83 noch im Sprachumfang enthalten, wird aber nicht mehr ausgelöst. Statt Numeric_Error wird jetzt Constraint_Error ausgelöst.

Storage_Error - wird ausgelöst, wenn mehr Speicher von einem Prozeß angefordert wird, als zur Verfügung steht.

Program_Error - wird bei verschiedenen Programmfehlern ausgelöst, z. B. wenn Daten oder Unterprogramme aus anderen, noch nicht elaborierten Paketen genutzt werden.

Tasking_Error - wird ausgelöst, wenn bei der Kommunikation über Rendezvous zwischen Prozessen Ausnahmen auftreten.

Das Auslösen dieser Ausnahmen erfolgt automatisch bei Fehlern während der Programmausführung.


Selbstdefinierte Ausnahmen

Neben diesen vordefinierten Ausnahmen erlaubt Ada auch die Deklaration von selbst-definierten Ausnahmen. Solch eine Ausnahme kann natürlich nicht vom Laufzeitsystem entdeckt werden, sondern wird durch eine "raise" -Anweisung explizit ausgelöst.

Alle selbstdefinierten Ausnahmen sind vom Typ "Exception" und haben die Form Fehlerbezeichnung1, Fehlerbezeichnung2, ... : Exception;

Beispiel:

Negative_Zahl : exception;


Die Deklaration von Ausnahmen kann an jeder beliebigen Stelle im Deklarationsteil erscheinen.

Typischerweise werden Ausnahmen jedoch in einer Paketspezifikation deklariert, damit sie programmweit benutzt werden können.

Ausnahmedeklarationen sind auch im Deklarationsteil von Unterprogrammrümpfen (subprogram_body <BNF>), Paketrümpfen (package_body <BNF>) und Blockanweisungen (block_statement <BNF>) erlaubt.

Im folgenden Beispiel löst die Eingabe einer negativen Zahl eine vordefinierte Ausnahme aus. Die Ausnahme wird im Ausnahmebehandler der Funktion behandelt und als selbstdefinierte Ausnahme an die nächste Ebene weitergereicht.

with Text_IO;

procedure Ausnahme is
   package Int_IO is new Text_IO.Integer_IO (Integer);

   Negative_Zahl : Exception; -- selbstdefinierte Ausnahme
   Anzahl : Natural := 0;
   Alter : Natural := 0;

   function Lies_Natuerliche_Zahl return Natural is
      N : Natural;
   begin
      Int_IO.Get (N);
      return N;
   exception
      when Constraint_Error =>
      -- Die Ausnahme wird auch bei sehr grossen Zahlen ausgeloest,
      -- die hier aber nicht beachtet werden sollen.
      Text_IO.Put_Line ("Sie haben eine negative Zahl eingegeben");
      raise Negative_Zahl; -- Funktion beenden und Ausnahme an
      -- Aufrufer weiterreichen, dieser kann dann gezielt darauf reagieren.
   end;
begin
   loop -- (A)
      begin
         Text_IO.Put ("Wieviele Kinder: ");
         Anzahl := Lies_Natuerliche_Zahl;
         exit;
      exception
         when Negative_Zahl =>
            Text_IO.Put_Line ("Anzahl muss groesser oder gleich 0 sein");
      end;
   end loop; -- weiter bei (A)

   if Anzahl > 0 then
      Text_IO.Put_Line ("Alter der Kinder:");
      for I in 1..Anzahl loop
         loop -- (B)
            Text_IO.Put (Integer'Image (I) & ". Kind:");
            begin
               Alter := Lies_Natuerliche_Zahl;
               exit;
            exception
               when Negative_Zahl =>
                  Text_IO.Put_Line ("Das Alter kann nicht negativ sein");
            end;
         end loop; -- weiter bei (B)
      end loop;
   else
      Text_IO.Put_Line ("Dann nicht !");
   end if;
end Ausnahme;


Eine "raise"-Anweisung kann überall im Anweisungsteil verwendet werden und bewirkt die sofortige Auslösung der entsprechenden Ausnahme. Die ihr folgenden Anweisungen werden nicht mehr ausgeführt.

Die "raise"-Anweisung hat die Form raise [Fehlerbezeichnung];

Sie kann sowohl für benutzerdefinierte als auch für vordefinierte Ausnahmen verwendet werden.


Beispiel :

with Text_IO;
procedure Haupt is
   --...
   Pruefung_Ausnahme : exception; -- Ausnahmevereinbarung
   --...
begin
   -- ...
   if ... then
      -- ... ;
   else
      raise Pruefung_Ausnahme; -- Auslösen der Ausnahme
   end if;
   -- ...
exception
   when Pruefung_Ausnahme => -- Abarbeiten der Ausnahme
   -- ... ;
   when others =>
      Put_Line ("Sonstige Ausnahme aufgetreten!");
      raise; -- Dieselbe Ausnahme wird weitergereicht!
end Haupt;


Soll eine Ausnahme als Indiz für einen fatalen Fehler gelten, so kann sie benutzt werden, um das Programm zu veranlassen, sich geordnet zu beenden (d. h. Retten von Daten, Speichern von Fehlerinformationen, Schalten von Fehlerlampen usw.).

Ein Ausnahmebehandler, der diese Funktionalität über alle Ebenen der Softwarestruktur weiterleitet, könnte folgenden Aufbau haben:

when Panik_Ausnahme =>
   System_Herunterfahren;
   raise Panik_Ausnahme;


Angenommen, dieser Ausnahmebehandler wird in einem Unterprogramm verwendet, so wird bei Auslösen dieser Ausnahme eine Prozedur System_Herunterfahren aufgerufen, die ein geordnetes Beenden des Unterprogrammes ermöglicht. Der Effekt der dann folgenden "raise"-Anweisung ist, daß die Ausnahme an die nächste Ebene weitergereicht wird. So kann über verschiedene Ebenen ein Fehler sukzessive bearbeitet werden.

Die Anweisung "raise" kann innerhalb eines Ausnahmebehandlers auch ohne einen Ausnahmenamen aufgerufen werden. Dieses bewirkt das erneute Aufrufen der Ausnahme.

Der folgende Ausnahmebehandler hat somit die gleiche Wirkung wie der vorherige:

when Panik_Ausnahme =>
   System_Herunterfahren;
   raise;



 
zurück
 Index   Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.