Anterior | Superior | Siguiente

Guía de referencia básica de Ada 95

Excepciones.

Concepto.

En la ejecución de un programa pueden darse muchas situaciones inesperadas: dispositivos que fallan, datos que se entran incorrectamente, valores fuera del rango esperado,... Incorporar todas las posibilidades de fallo y casos extraños en la lógica de un algoritmo puede entorpecer su legibilidad y su eficiencia; no tenerlas en cuenta produce que los programas aborten de forma incontrolada y puedan generarse daños en la información manejada. Los mecanismos de control de excepciones permiten contemplar este tipo de problemas separándolos de lo que es el funcionamiento "normal" del algoritmo; una excepción en Ada 95 es un objeto que identifica la ocurrencia de una situación anormal.

En el estándar de Ada están definidas las siguientes excepciones básicas:

Constraint_error Ocurre cuando se intenta asignar a una variable un valor no válido o cuando se intenta acceder a una posición de un array fuera del rango permitido.
Program_error Ocurre en situaciones extrañas cuando parte de un programa no es accesible o cuando se alcanza el "end" de una función sin encontrar un "return".
Storage_error Ocurre cuando se agota la memoria disponible.
Tasking_error Está relacionado con errores en programas que utilicen programación concurrente.

Además, en otras librerías (Ej. las relacionadas con entrada/salida) se definen excepciones específicas.

Declaración.

El programador puede declarar sus propias excepciones para identificar problemas particulares que puedan surgir en sus programas. Las declaración está sujeta a las reglas generales de declaración y consta de: una lista de identificadores, dos puntos (":") y la palabra exception.

Error1, Error2: exception; --se declaran dos excepciones

Lanzamiento.

Al hecho de activar una excepción cuando ocurre la situación para la que está prevista se le conoce como "lanzar" la excepción; básicamente esto consiste en interrumpir la ejecución "normal" del programa e intentar localizar una sección de código capaz de hacerse cargo de la excepción y resolverla. Las excepciones predefinidas se lanzan automáticamente cuando ocurre la situación para la que se han previsto; se pueden también lanzar las excepciones predefinidas o, más probablemente, las declaradas en el programa usando una sentencia raise.

raise Error1; --lanza la excepción Error1;

Manejo.

Un manejador de excepciones es un conjunto de instrucciones destinadas a ejecutarse en respuesta al lanzamiento de una excepción. Los manejadores de excepciones empiezan con una cláusula when seguida de la lista de excepciones a las que responde unidas por el operador "|" (or) y a continuación las instruciones a ejecutar.

when Error1 | Error2 =>
   --aquí se ponen las instrucciones a ejecutar
   --cuando ocurra la excepción Error1 o la Error2
   ...

Los manejadores se agrupan en una sección situada al final de cualquier bloque begin...end que contenga el algoritmo cuyas excepciones se quiere controlar; esta sección se abre con la palabra exception.

begin
   --Instrucciones "normales" en las que puede haber problemas
   ...
exception
   --manejadores de excepciones
   ...
end;

Durante la ejecución de un algoritmo, cuando se lanza una excepción el control es transferido a la sección de excepciones situada al final del bloque begin...end en el que se engloba y allí se busca un manejador que tenga en su lista la excepción lanzada y se ejecuta. Si no se encuentra ningún manejador que tenga a la excepción en su lista o si el bloque begin...end no tiene sección de tratamiento de excepciones la búsqueda del manejador continúa en el siguiente bloque activo más externo (aquel que inició la ejecución del actual). Mientras no se encuentre un manejador apropiado la búsqueda continúa hasta alcanzar el procedimiento principal; si en éste tampoco se encuentra un manejador acorde a la excepción lanzada, se aborta la ejecución del programa. Cuando un programa aborta se imprime en pantalla información acerca de qué excepción ha ocurrido y de dónde se ha producido, por si pudiera resultar de alguna utilidad.

Ejemplo.

with Text_IO;
use Text_IO;

procedure Excepciones is
  package Entero_IO is new Integer_IO(Integer);
  package Real_IO is new Float_IO(Float);
  use Entero_IO, Real_IO;

  Divide_por_cero: exception; --declaración de una excepción
  --llamada Divide_por_cero
  procedure Leer(x,y: out integer) is
  --el procedimiento Leer ilustra cómo se controla una
  --excepción de forma que el programa se recupere y
  --continúe operando
  begin
    --el bucle permite reintentar la lectura si falla
    loop
      --es necesario abrir un bloque para poder manejar
      --las excepciones dentro del bucle
      begin
        --el algoritmo que puede producir la excepción
        --son las siguientes tres líneas
        put("Déme dos números enteros: ");
        get(x);
        get(y);
        exit; --si se llega a este punto el algoritmo
              --se ha ejecutado sin problemas y se
              --abandona el bucle
      exception
        --Data_Error se produce si no se teclea un literal entero
        --válido. Se captura y se hacen las operaciones
        --oportunas para poder reintentar la lectura
        when Data_error => --se captura la excepción
          --se informa al usuario de su error
          put_line("Por favor, teclee correctamente");
          skip_line; --se vacía el buffer de entrada
                     --que contiene un valor incorrecto
      end;
    end loop; --se deja que el bucle cicle
              --para reintentar la lectura
  end Leer;

  function Divide1(x,y: in integer) return float is
  --La función Divide1 ilustra cómo, tras capturar una
  --excepción y hacer algunas operaciones, se
  --puede relanzar para que un bloque más externo
  --continúe su manejo
    r: float;
  begin
    r := float(x) / float(y);
    return r;
  exception
    when Constraint_error =>
      put_line("El divisor es cero");
      raise; --se relanza Constraint_error
  end Divide1;

  function Divide2(x,y: in integer) return float is
  --La función Divide2 ilustra cómo se lanza
  --una excepción
    r: float;
  begin
    if y = 0 then
      raise Divide_por_cero;
    else
      r := float(x) / float(y);
      return r;
    end if;
  end Divide2;

  a, b: integer;
begin
  Leer(a,b);
  put("El cociente es: ");
  if a > b then
    put(Divide1(a,b));new_line;
  else
    put(Divide2(a,b));new_line;
  end if;
exception
  when Constraint_error|Divide_por_cero =>
    new_line;
    put_line("No se puede dividir por cero");
  when others =>
    new_line;
    put_Line(" Error desconocido");
end Excepciones;

© Grupo de Estructuras de Datos y Lingüística Computacional - ULPGC.

Anterior | Superior | Siguiente