Programación en Ada/Excepciones
En Ada, cuando se produce algún error durante la ejecución de un programa, se eleva una excepción. Dicha excepción puede provocar la terminación abrupta del programa, pero se puede controlar y realizar las acciones pertinentes. También se pueden definir nuevas excepciones que indiquen distintos tipos de error.
Excepciones predefinidas
[editar]En Ada, dentro del paquete Standard, existen unas excepciones predefinidas, éstas son:
- Constraint_Error
- cuando se intenta violar una restricción impuesta en una declaración, tal como indexar más allá de los límites de un array o asignar a una variable un valor fuera del rango de su subtipo.
- Program_Error
- se produce cuando se intenta violar la estructura de control, como cuando una función termina sin devolver un valor.
- Storage_Error
- es elevada cuando se requiere más memoria de la disponible.
- Tasking_Error
- cuando hay errores en la comunicación y manejo de tareas.
- Numeric_Error
- en Ada 83 se podía presentar cuando ocurría un error aritmético. A partir del estándar Ada 95, desaparece por motivos de portabilidad y pasa a ser un renombrado de Constraint_Error. Por ejemplo, en Ada 83 al dividir entre cero podía saltar Constraint_Error o Numeric_Error (dependiendo del compilador). En Ada 95 este error siempre levanta Constraint_Error.
- Name_Error
- se produce cuando se intenta abrir un fichero que no existe.
Manejador de excepciones
[editar]Cuando se espere que pueda presentarse alguna excepción en parte del código del programa, se puede escribir un manejador de excepciones en las construcciones que lo permitan (bloques o cuerpos de subprogramas, paquetes o tareas), aunque siempre está el recurso de incluir un bloque en cualquier lugar del código.
Su sintaxis sería:
manejador_excepción ::=when
[ identificador : ] elección_excepción { | elección_excepción } => secuencia_sentencias elección_excepción ::= identificador |others
A la sentencia que comienza por when
, se le denomina manejador de excepción.
La palabra reservada others
indica cualquier otra excepción y debe ser la única y última opción. Por ejemplo, en un bloque:
begin
-- ...
exception
when
Constraint_Error => Put ("Error de rango.");when
Program_Error | Tasking_Error => Put ("Error de flujo.");when
others
=> Put ("Otro error.");end
;
En el momento en el que se produzca la elevación de Constraint_Error
durante la ejecución de la secuencia de sentencias entre begin
y
exception
, el flujo de control se interrumpe y se
transfiere a la secuencia de sentencias que siguen a la palabra
reservada =>
del manejador correspondiente.
Otro ejemplo con una función:
function
Mañana (Hoy: TDía)return
TDíais
begin
return
TDía'Succ(Hoy);exception
when
Constraint_Error =>return
TDía'First;end
Mañana;
Nótese que no se puede devolver nunca el control a la unidad donde se elevó la excepción. Cuando se termina la secuencia de sentencias del manejador, termina también la ejecución de dicha unidad.
Si no se controla una excepción, ésta se propaga dinámicamente por las sucesivas unidades invocantes hasta que se maneje en otra o directamente termina la ejecución del programa proporcionando un mensaje con la excepción provocada por pantalla.
Declaración y elevación de excepciones
[editar]Normalmente, es probable prever una situación de error que no se encuentra entre las excepciones predefinidas, por ello, se puede declarar excepciones. Por ejemplo:
Error: exception
;
Con lo que se puede elevar dicha excepción en el momento pertinente mediante la sentencia raise, cuya sintaxis es:
elevación_excepción ::= raise
[ identificador ] ;
Por ejemplo, en un paquete de manejo de una pila estática de números enteros:
package
Pila_enterosis
ErrorPilaEnteros:exception
;procedure
Poner (X: Integer);function
Quitarreturn
Integer;end
Pila_enteros;package
body
Pila_enterosis
Max:constant
:= 100; Pila:array
(1..Max)of
Integer; Cima: Integerrange
0..Max;procedure
Poner (X: Integer)is
begin
if
Cima = Maxthen
raise
ErrorPilaEnteros;-- Se eleva la excepción.
end
if
; Cima := Cima + 1; P(Cima) := X;end
Poner;function
Quitarreturn
Integeris
begin
if
Cima = 0then
raise
ErrorPilaEnteros;-- Se eleva la excepción.
end
if
; Cima := Cima - 1;return
Pila(Cima+1);end
Quitar;begin
Cima := 0;end
Pila_enteros;
Obsérvese que no hace falta else en la sentencias if, pues al elevar la excepción, finaliza la ejecución del subprograma.
Ahora se podría escribir:
declare
use
Pila_enteros;begin
Poner (5);-- ...
exception
when
ErrorPilaEnteros =>-- ... Manipulación incorrecta de la pila.
when
others
=>-- ...
end
;
Si se quiere que dicha excepción no se propague más allá de la unidad en la que se elevó pero no se quiere manejar, se puede emplear una única sentencia vacía (null) dentro de su manejador correspondiente:
procedure
Vaciar_pila_enterosis
Basura: Integer;use
Pila_enteros;begin
loop
Basura := Quitar;end
loop
;exception
when
ErrorPilaEnteros =>null
;end
Vaciar_pila_enteros;
Aunque esto no evitaría que se terminara la ejecución de la unidad.
En el caso en el que se quiera propagar una excepción después de haber ejecutado las sentencias pertinentes, se incluiría una sentencia raise dentro del manejador:
-- ...
exception
when
ErrorPilaEnteros => Put ("Pila utilizada incorrectamente."); Vaciar_pila_enteros;raise
ErrorProcesamieto;-- Se propaga otra excepción.
end
;
En este caso se propaga otra excepción, pero podría haber sido la misma simplemente con raise, sin crear una nueva ocurrencia de la excepción, por ejemplo:
-- ...
exception
when
FalloEnVálvula => Put ("Se ha producido un fallo en la válvula.");raise
;-- Se propaga la misma excepción del manejador.
end
;
Así, se puede realizar un manejo de la excepción en varias capas, realizando sucesivas acciones en cada una de ellas. Dicha sentencia raise sin argumentos debe ser invocada directamente en el manejador, no es posible invocarla en un procedimiento llamado por el manejador.
Información de la excepción
[editar]Ada proporciona información sobre una determinada excepción haciendo uso del paquete predefinido Ada.Exceptions y tras obtener la ocurrencia de la excepción mediante esta notación:
when
Ocurrencia : ErrorSensor =>
Put_Line (Ada.Exceptions.Exception_Information (Ocurrencia));
Manual de referencia de Ada
[editar]Enlaces externos
[editar]- Excepciones: artículo de la Universidad de Valladolid. Ejemplos en Ada y Eiffel.