5. Exceptions: Error Control - JulTob/Ada Wiki

An exception situation arises when an operation is invoked and cannot be completed in a normal fashion and certain predicates fail to hold.

The use of exception control returns the control to the upper level to deal with it, and if not dealt with pass it up, all the way up to the computer operating system. The speed is immediate, so it's the best option to regain control over the exception situation, especially if wasting time doing other processing might cause damage to hardware or hurt someone.

The invoked operation detects this failure and allows the invoker to deal with the situation appropriately.

Exception situations are not always errors.

They may be boundary conditions whose significance is known primarily to the operation's invoker. Exceptions serve to generalize operations (making them usable in a wider variety of situations) because:

  • The response to an exception situation is provided by the invoker instead of by the operation itself.

  • An arbitrary, operation-defined response to the situation can be replaced by an appropriate user-defined response.

Let this sink in: Ada has control of Errors and Exceptions integrated into the language.

Since exceptions are not supported explicitly by the most commonly used programming languages, few programmers and system designers have experience in making effective use of this language feature.

In Ada it’s not an advanced feature. It’s so basic that all al programs are structured in a begin-exception-end.

begin
 ...
exception
  When <Error_identificator> =>
    <response>
end;

We can write the Square root example in a better way, changing the if for:

...   begin
         Put(Sqrt(X))
      exception
         When Constraint_Error =>
              Put(“not calculable”);
      end; ...

This way we don’t have to prevent every possible error. If Put() fails, or anything between a begin and exception, it automatically goes to the exception handler.

The exception domain can (and should?) exist between every begin and end.

Constraint_Error is an Exception type from the standard library. If another exception occurs, it passes control to the nesting process, and then up until no more processes are found, and terminates the program.

Note that a program will not compile if the rules of Ada are violated. Those programs are called illegal and can’t even happen.

First, identify the input assertions associated with an operation, i.e., the assumptions and preconditions that allow the operation to complete in a ``normal'' manner.

  • Then evaluate each assertion, using criteria such as:
    • An operation's behavior may be undefined if an operation is invoked when an input assertion is unsatisfied. Are the consequences of such behavior likely to be important? Depending on the answers to these questions, a designer can decide whether an exception situation should be handled by signalling an exception condition.

Exceptions only deal with Execution time problems. Some errors (like not initializing) cannot be detected.

Among these, problems like trying to access an array outside the range can be easily avoided by using a subtype with the range, or indicating the constraints:

Subtype Buffer_Index is Integer range 1 .. 80;

Index: Integer range  1..80;

It’s remarkable to point out that the program doesn’t slow down by Exception control.

Exceptions are typically defined in a package specification.

Divide_By_Zero : exception;

And are called by a raise call, that aborts execution.

raise Divide_By_Zero;

Standard exceptions

The four Standard Exceptions are built into the compiler:

Constraint_Error Range violations.
Program_Error Ill formed programs executed.
Storage_Error Out of memory.
Tasking_Error Tasking Problems.
others Codeword for anything triguered

These are part of the Language itself, but others are part of the Standard Library.

Exceptions in loops.

We can control the flow in loops by exceptions with the use of a begin block.

for I in 1..N loop
 begin 
  Put(I);
 Exception
  when others =>
    Exit; -- Exits Loop 
 End; 
End Loop;

Exception Examples

For a POP operation of a stack or queue, an input predicate is The stack or queue has at least one element. An exception situation occurs when POP is invoked and this predicate does not hold.

  • For a READ operation on a file, an input predicate is There exists a record to be read.

  • For a TABLE_LOOKUP operation, an input predicate is the sought-for value exists.

  • For MATRIX_INVERSION, an input predicate is an inverse exists.

An exception condition is signalled to the invoker of an operation when the corresponding exception situation is detected. A handler for the condition specifies the invoker's response to the exception situation.

with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Divide is
   X, Y, D: Float; 
   PD   : access Float;
begin 
   Get (X);
   Get (Y);

   D  := Float(X) / Float(Y);
   PD := new Float'(D); 
   
   Put (D); 
exception 
   when Data_Error | Constraint_Error =>
      put_line("Error en los datos");
   when Storage_Error =>
      put_line("Memoria insuficiente");
   when others =>
      put_line("Error inesperado");
end Divide;
⚠️ **GitHub.com Fallback** ⚠️