Capítulo 6. Excepciones y manejo de excpeciones
6
6.1.1
6.1.2
6.1.3
6.1.4
Excepciones y manejo de excepciones............................................................................................ 2
6.1 Manejo de excepciones en los lenguajes de tiempo real primitivos _................................... 2
Retorno de un valor inusual......................................................................................... 2
Bifurcación forzada ..................................................................................................... 3
goto no local ................................................................................................................ 3
Variable de procedimiento........................................................................................... 3
6.2 Manejo de excepciones moderno ........................................................................................ 4
Excepciones y su representacion ................................................................................. 4
6.2.1
El dominio de un manejador de excepciones .............................................................. 5
6.2.2
6.2.3
Propagación de excepciones........................................................................................ 6
6.2.4 Modelo de reanudación y modelo ............................................................................... 7
Bloques de recuperación y excepciones ............................................................................ 11
6.3
Rafael Álvarez García
Última revisión 03-12-07
[email protected]
Nota importante:
Este documento no pretende reemplazar al material propuesto por la UNED para la
asignatura Sistemas en Tiempo Real. Cualquier sugerencia, comentario o corrección sobre
este documento, envíelo a
[email protected] para poder realizar los cambios
necesarios.
1
6 Excepciones y manejo de excepciones
Existen ciertos requisitos generales para cualquier mecanismo de manejo de excepciones:
(Rl) Como ocurre con cualquier aspecto de un lenguaje, el mecanismo debe ser fácil de
comprender y utilizar.
(R2) El código de manejo de excepciones no debiera complicar el aspecto del programa hasta el
punto de obscurecer la comprensión de la operación normal del programa (sin errores).
(R3) El mecanismo deberá diseñarse de modo que solo suponga una sobrecarga en la ejecución
cuando se maneja una excepción. Aunque la mayoría de las aplicaciones requieren que las
prestaciones de un programa que use excepciones no se vea afectada negativamente bajo
condiciones normales, no tiene por que ser siempre así. Bajo ciertas circunstancias, en concreto
cuando sea primordial la rapidez en la recuperación, una aplicación puede estar preparada para
tolerar cierta pequeña sobrecarga en una operación normal libre de errores.
(R4) El mecanismo deberá permitir un tratamiento uniforme de las excepciones detectadas
tanto por el entorno como por el programa. Por ejemplo, una excepción como el desbordamiento
aritmético, que es detectada por el hardware, debiera ser manejada exactamente de la misma forma
que una excepción generada por el programa como resultado de un fallo en una aserción.
(R5) El mecanismo de excepciones deberá permitir la programación de acciones de
recuperación.
6.1 Manejo de excepciones en los lenguajes de
tiempo real primitivos
Aunque los términos «excepción» y «manejo de excepciones» se han puesto de moda solo
recientemente, se refieren simplemente a una forma de programar para contener y manejar las
situaciones de error. En consecuencia, la mayoría de los lenguajes de programación disponen de
medios para manejar al menos algunas excepciones. Esta sección describe brevemente estos
mecanismos en relación con los requisitos mencionados anteriormente.
6.1.1 Retorno de un valor inusual
Una de las formas más primitivas de mecanismo de manejo de excepciones es el retorno de un
valor inusual o retorno de error desde un procedimiento o una función. Su principal ventaja es que
es simple, y que para su implementación no precisa de ningún mecanismo nuevo en el lenguaje. C
soporta este modo, y se usa así:
Como puede verse, aunque presenta el requisito de simplicidad (Rl) y permite programar
acciones para la recuperación (R5), no satisface (R2), (R3) y (R4). El código se complica, supone
una sobrecarga, y no queda claro como manejar los errores detectados desde el entorno.
A lo largo de este libro, C se utiliza junto con POSIX. Las condiciones de error en POSIX se
indican con valores de retorno distinto de cero (cada uno con un nombre simbólico). Por seguridad,
al llamar a una función del sistema debiera comprobarse el valor devuelto para ver si se ha
producido un error inesperado; aunque, como se puede ver, se obscurece la estructura del código.
2
Por esto, y con fines pedagógicos, en este libro se emplea una interfaz de POSIX estilizada. Para
cada llamada POSIX al sistema, se supone definida una macro que efectuara la comprobación del
error. Por ejemplo, una llamada al sistema como sys_call que tome un parámetro, tendrá definida la
siguiente macro,
tdefine SYS_CALL(A) if(sys„call(A) != 0} error()
donde error es una función que efectúa el procesamiento del error. Así, en la llamada solo
aparecerá SYS„CALL (param).
6.1.2 Bifurcación forzada
En los lenguajes de ensamblado, la forma usual de manejar excepciones en subrutinas es
sobrepasar el retomo. Es decir, se sobrepasa la instrucción inmediatamente posterior a la llamada a
la subrutina para indicar la presencia (o ausencia) de errores. Para ello, la subrutina incrementa su
dirección de retorno (contador de programa) en el tamaño de una instrucción de salto simple con el
fin de indicar un retorno sin (o con) error. En caso de que sea posible más de un retorno
excepcional, la subrutina presupondrá que tras la llamada hay varias instrucciones de salto, y
manipulara convenientemente el contador de programa.
En el caso de un retorno normal, la subrutina incrementara la dirección de retorno en dos ins-
trucciones jmp.
Si bien esta practica implica poca sobrecarga (R3) y permite programar acciones de
recuperación (R5), obscurece la estructura del programa, violando así los requisitos (Rl) y (R2).
Tampoco puede satisfacerse (R4).
6.1.3 goto no local
Una versión de la bifurcación forzada sobre un lenguaje de alto nivel requeriría pasar como
parámetros las diferentes etiquetas, o disponer de variables de etiqueta estándar (una variable de
etiqueta es un objeto al que se le puede asignar una dirección del programa y que puede ser usado
para transferir el control). RTL/2 es un caso de lenguaje de tiempo real primitivo que proporciona
esta posibilidad bajo la forma de un goto no local. RTL/2 emplea bricks (ladrillos) para estructurar
sus programas: un brick pueden ser datos (delimitado por data. . . enddata), un procedimiento (de
limitado por proc. . . endproc), o una pila (indicada por stack). El sistema define un tipo especial de
brick de datos llamado data svc, Uno de estos brick's (rrerr) proporciona un mecanismo estándar de
manejo de errores que incluye una variable de etiqueta de error llamada er 1.
Vemos que cuando se emplea de esta forma, el goto es mas que un simple salto: implica un
retorno anormal de un procedimiento, por lo que habrá que desapilar datos de la pila hasta restaurar
el entorno del procedimiento que contiene la declaración de la etiqueta. La penalización por el
desapilamiento se aplica solo cuando aparece un error, por lo que se satisface el requisito (R3),
Aunque el empleo de goto es muy flexible (satisfaciendo R4 y R5), puede desembocar en
programas muy obscuros. En consecuencia, no satisface los requisitos (Rl y R2).
6.1.4 Variable de procedimiento
En RTL/2, la etiqueta de error suele emplearse con los errores irrecuperables, recurriéndose a
una variable de procedimiento de error cuando el control debe retornar al punto donde se origino el
error.
3
De nuevo, el principal reproche que puede hacerse a esta aproximación es que los programas
pueden volverse muy difíciles de entender y de mantener.
6.2 Manejo de excepciones moderno
En las aproximaciones tradicionales al manejo de excepciones suele ocurrir que el código de
manejo se entremezcla con el flujo normal de ejecución del programa. Actualmente, se tiende a
incluir funcionalidades de manejo de excepciones directamente en el lenguaje, resultando un
mecanismo mas estructurado. La naturaleza exacta de estas facilidades varía de un lenguaje a otro,
aunque se pueden identificar algunas formas de proceder comunes. En las secciones siguientes se
discuten estos mecanismos.
6.2.1 Excepciones y su representación
Sabemos que hay dos técnicas principales para detectar errores: detección desde el entorno y
desde la aplicación. También, según el retraso en la detección del error, puede ser preciso generar la
excepción síncrona o asíncronamente. La excepción síncrona se genera como respuesta inmediata a
una operación inapropiada de un fragmento de código. La excepción asíncrona se genera cierto
tiempo después de que ocurra la operación que da lugar a la aparición del error. Puede generarse
desde el proceso que ejecuto la operación originalmente, o en otro proceso. En consecuencia,
existen cuatro clases de excepciones;
• Detectada por el entorno y generada sincrónicamente, como por ejemplo una violación de
los límites
Comentarios de: Capitulo 6. Excepciones y manejo de excepciones (0)
No hay comentarios