En informática y programación de computadoras , el manejo de excepciones es el proceso de responder a la ocurrencia de excepciones (condiciones anómalas o excepcionales que requieren un procesamiento especial) durante la ejecución de un programa . En general, una excepción interrumpe el flujo normal de ejecución y ejecuta un manejador de excepciones registrado previamente ; los detalles de cómo se hace esto dependen de si se trata de una excepción de hardware o software y de cómo se implementa la excepción de software. El manejo de excepciones, si se proporciona, se facilita mediante un lenguaje de programación especializadoconstrucciones, mecanismos de hardware como interrupciones o facilidades de comunicación entre procesos (IPC) del sistema operativo (SO) como señales . Algunas excepciones, especialmente las de hardware, pueden manejarse con tanta elegancia que la ejecución puede reanudarse donde se interrumpió.
Un enfoque alternativo para el manejo de software de excepción es la comprobación de errores , que mantiene el flujo normal del programa con posteriores comprobaciones explícitas para riesgos especiales mencionados al usar retorno valores, un auxiliar variables globales tales como C ' s errno , o indicadores de estado de coma flotante. La validación de entrada , que filtra de forma preventiva casos excepcionales, también es un enfoque.
En hardware
Los mecanismos de excepción de hardware son procesados por la CPU. Está destinado a soportar, por ejemplo, la detección de errores y redirige el flujo del programa a las rutinas de servicio de manejo de errores. El estado anterior a la excepción se guarda, por ejemplo, en la pila. [1]
Trampas / manejo de excepciones de hardware: punto flotante IEEE 754
El manejo de excepciones en el estándar de hardware de punto flotante IEEE 754 se refiere en general a condiciones excepcionales y define una excepción como "un evento que ocurre cuando una operación en algunos operandos en particular no tiene un resultado adecuado para cada aplicación razonable. Esa operación puede señalar una o más excepciones invocando el valor predeterminado o, si se solicita explícitamente, un manejo alternativo definido por el idioma ".
De forma predeterminada, una excepción IEEE 754 es reanudable y se maneja sustituyendo un valor predefinido para diferentes excepciones, por ejemplo, infinito para una excepción de división por cero, y proporcionando indicadores de estado para verificar más tarde si se produjo la excepción (consulte el lenguaje de programación C99 para una ejemplo de manejo de excepciones IEEE 754). Un estilo de manejo de excepciones habilitado por el uso de indicadores de estado implica: primero calcular una expresión usando una implementación rápida y directa; comprobar si falló probando los indicadores de estado; y luego, si es necesario, llamar a una implementación más lenta y numéricamente más robusta. [2]
El estándar IEEE 754 usa el término "captura" para referirse a la llamada de una rutina de manejo de excepciones proporcionada por el usuario en condiciones excepcionales, y es una característica opcional del estándar. El estándar recomienda varios escenarios de uso para esto, incluida la implementación de la sustitución previa no predeterminada de un valor seguida de la reanudación, para manejar de manera concisa las singularidades extraíbles . [2] [3] [4]
El comportamiento predeterminado de manejo de excepciones IEEE 754 de reanudación después de la sustitución previa de un valor predeterminado evita los riesgos inherentes al cambio de flujo de control del programa en excepciones numéricas. Por ejemplo, en 1996, el vuelo inaugural del Ariane 5 (Vuelo 501) terminó en una explosión catastrófica debido en parte a la política de manejo de excepciones del lenguaje de programación Ada de abortar el cálculo por error aritmético, que en este caso era un punto flotante de 64 bits. a desbordamiento de conversión de enteros de 16 bits . [3] En el caso del vuelo 501 de Ariane, los programadores protegieron solo cuatro de las siete variables críticas contra el desbordamiento debido a preocupaciones sobre las limitaciones computacionales de la computadora de a bordo y se basaron en lo que resultaron ser suposiciones incorrectas sobre el posible rango de valores para las tres variables desprotegidas porque reutilizaron código del Ariane 4, para lo cual sus suposiciones eran correctas. [5] Según William Kahan , la pérdida del vuelo 501 se habría evitado si se hubiera utilizado la política de manejo de excepciones IEEE 754 de sustitución predeterminada porque la conversión desbordante de 64 bits a 16 bits que hizo que el software abortara ocurrió en un fragmento de código que resultó ser completamente innecesario en el Ariane 5. [3] El informe oficial sobre el accidente (realizado por una junta de investigación encabezada por Jacques-Louis Lions ) señaló que "Un tema subyacente en el desarrollo de Ariane 5 es el sesgo hacia la mitigación de fallas aleatorias . El proveedor del sistema de navegación inercial (SRI) solo estaba siguiendo la especificación que se le dio, que estipulaba que en caso de detectarse alguna excepción, el procesador debía detenerse. La excepción que ocurrió no se debió a una falla aleatoria sino a un error de diseño. La excepción se detectó, pero se manejó de manera inapropiada porque se había tomado la opinión de que el software debe considerarse correcto hasta que se demuestre que tiene la falla. [...] Si bien el fallo se debió a un error sistemático en el diseño del software, se pueden introducir mecanismos para mitigar este tipo de problema. Por ejemplo, las computadoras dentro de los SRI podrían haber continuado proporcionando sus mejores estimaciones de la información de actitud requerida . Existe un motivo de preocupación de que se debería permitir, o incluso exigir, una excepción de software para hacer que un procesador se detenga mientras se manipulan equipos de misión crítica. De hecho, la pérdida de una función de software adecuada es peligrosa porque el mismo software se ejecuta en ambas unidades SRI. En el caso de Ariane 501, esto resultó en el apagado de dos unidades críticas de equipo aún en buen estado ". [6]
Desde el punto de vista del procesamiento, las interrupciones de hardware son similares a las excepciones reanudables, aunque normalmente no están relacionadas con el flujo de control del programa de usuario .
Facilidades de manejo de excepciones proporcionadas por el sistema operativo
Los sistemas operativos similares a Unix brindan facilidades para manejar excepciones en programas a través de IPC . Por lo general, las interrupciones causadas por la ejecución de un proceso son manejadas por las rutinas de servicio de interrupciones del sistema operativo, y el sistema operativo puede enviar una señal a ese proceso, que puede haber pedido al sistema operativo que registre un manejador de señales para ser llamado. cuando se genera la señal, o dejar que el sistema operativo ejecute una acción predeterminada (como terminar el programa). Los ejemplos típicos son SIGSEGV , SIGBUS , SIGILL y SIGFPE .
Otros sistemas operativos, por ejemplo, OS / 360 y sucesores , pueden utilizar diferentes enfoques en lugar o además de IPC.
En software
El manejo de excepciones de software y el soporte proporcionado por las herramientas de software difieren un poco de lo que se entiende por manejo de excepciones en hardware, pero están involucrados conceptos similares. En los mecanismos del lenguaje de programación para el manejo de excepciones, el término excepción se usa típicamente en un sentido específico para denotar una estructura de datos que almacena información sobre una condición excepcional. Un mecanismo para transferir el control o generar una excepción se conoce como lanzamiento . Se dice que se lanza la excepción . La ejecución se transfiere a una "captura".
Desde el punto de vista del autor de una rutina , generar una excepción es una forma útil de señalar que una rutina no podría ejecutarse normalmente, por ejemplo, cuando un argumento de entrada no es válido (por ejemplo, el valor está fuera del dominio de una función ) o cuando un recurso del que depende no está disponible (como un archivo faltante, un error de disco duro o errores de memoria insuficiente), o que la rutina ha detectado una condición normal que requiere un manejo especial, por ejemplo, atención, fin de archivo . En sistemas sin excepciones, las rutinas deberían devolver algún código de error especial . Sin embargo, esto a veces se complica por el problema de semipredicado , en el que los usuarios de la rutina necesitan escribir código adicional para distinguir los valores de retorno normales de los erróneos.
Los lenguajes de programación difieren sustancialmente en su noción de lo que es una excepción. Las lenguas contemporáneas se pueden dividir aproximadamente en dos grupos: [7]
- Los lenguajes donde las excepciones están diseñadas para usarse como estructuras de control de flujo: Ada, Modula-3, ML, OCaml, PL / I, Python y Ruby se incluyen en esta categoría.
- Lenguajes donde las excepciones solo se utilizan para manejar situaciones anormales, impredecibles y erróneas: C ++, [8] Java, [9] C #, Common Lisp, Eiffel y Modula-2.
Kiniry también señala que "el diseño del lenguaje solo influye parcialmente en el uso de excepciones y, en consecuencia, en la forma en que se manejan las fallas parciales y totales durante la ejecución del sistema. La otra influencia importante son los ejemplos de uso, generalmente en bibliotecas centrales y ejemplos de código en libros, artículos de revistas y foros de discusión en línea, y en los estándares de código de una organización ". [7]
Las aplicaciones contemporáneas enfrentan muchos desafíos de diseño al considerar estrategias de manejo de excepciones. Particularmente en las aplicaciones modernas de nivel empresarial, las excepciones a menudo deben cruzar los límites del proceso y los límites de la máquina. Parte del diseño de una estrategia sólida de manejo de excepciones es reconocer cuando un proceso ha fallado hasta el punto en que no puede ser manejado económicamente por la parte de software del proceso. [10]
Historia
Manejo de excepciones de software desarrollado en Lisp en las décadas de 1960 y 1970. Esto se originó en LISP 1.5 (1962), donde las excepciones fueron capturadas por la ERRSET
palabra clave, que regresaba NIL
en caso de error, en lugar de terminar el programa o ingresar al depurador. [11] La generación de errores se introdujo en MacLisp a finales de la década de 1960 mediante la ERR
palabra clave. [11] Esto se usó rápidamente no solo para generar errores, sino también para el flujo de control no local, y por lo tanto se amplió con dos nuevas palabras clave, CATCH
y THROW
(MacLisp junio de 1972), reserva ERRSET
y ERR
para el manejo de errores. El comportamiento de limpieza que ahora se denomina generalmente "finalmente" se introdujo en NIL (Nueva implementación de LISP) a mediados o finales de la década de 1970 como UNWIND-PROTECT
. [12] Esto fue luego adoptado por Common Lisp . Contemporáneo con esto fue dynamic-wind
en Scheme, que manejó excepciones en cierres. Los primeros artículos sobre el manejo estructurado de excepciones fueron Goodenough (1975a) y Goodenough (1975b) . [13] El manejo de excepciones fue posteriormente ampliamente adoptado por muchos lenguajes de programación desde la década de 1980 en adelante.
PL / utilicé excepciones de ámbito dinámico, sin embargo, los lenguajes más recientes utilizan excepciones de ámbito léxico. El manejo de excepciones PL / I incluyó eventos que no son errores, por ejemplo, atención, fin de archivo, modificación de las variables listadas. Si bien algunos lenguajes más recientes admiten excepciones sin errores, su uso no es común. [ cita requerida ]
Originalmente, el manejo de excepciones de software incluía tanto excepciones reanudables (semántica de reanudación), como la mayoría de las excepciones de hardware, como excepciones no reanudables (semántica de terminación). Sin embargo, la semántica de reanudación se consideró ineficaz en la práctica en las décadas de 1970 y 1980 (ver discusión de estandarización de C ++, citada a continuación) [14] y ya no es de uso común, aunque proporcionada por lenguajes de programación como Common Lisp, Dylan y PL / I.
Semántica de terminación
Los mecanismos de manejo de excepciones en los lenguajes contemporáneos no suelen ser reanudables ("semántica de terminación") a diferencia de las excepciones de hardware, que normalmente son reanudables. Esto se basa en la experiencia de usar ambos, ya que existen argumentos teóricos y de diseño a favor de cualquiera de las decisiones; estos fueron ampliamente debatidos durante las discusiones de estandarización de C ++ 1989-1991, lo que resultó en una decisión definitiva para la semántica de terminación. [14] Sobre el fundamento de tal diseño para el mecanismo C ++, Stroustrup señala:
[En] la reunión de Palo Alto [C ++ estandarización] en noviembre de 1991, escuchamos un resumen brillante de los argumentos a favor de la semántica de terminación respaldado con experiencia personal y datos de Jim Mitchell (de Sun, anteriormente de Xerox PARC). Jim había utilizado el manejo de excepciones en media docena de idiomas durante un período de 20 años y fue uno de los primeros defensores de la semántica de reanudación como uno de los principales diseñadores e implementadores del sistema Cedar / Mesa de Xerox . Su mensaje fue
- “Se prefiere la terminación a la reanudación; esto no es una cuestión de opinión, sino de años de experiencia. La reanudación es seductora, pero no válida ".
Respaldó esta declaración con la experiencia de varios sistemas operativos. El ejemplo clave fue Cedar / Mesa: fue escrito por personas a las que les gustó y usó la reanudación, pero después de diez años de uso, solo quedaba un uso de reanudación en el sistema de medio millón de líneas, y esa fue una investigación de contexto. Debido a que la reanudación no era realmente necesaria para una consulta de contexto de este tipo, la eliminaron y encontraron un aumento significativo de velocidad en esa parte del sistema. En todos y cada uno de los casos en los que se había utilizado la reanudación, a lo largo de los diez años, se había convertido en un problema y lo había reemplazado por un diseño más apropiado. Básicamente, cada uso de la reanudación había representado una falla en mantener separados los niveles de abstracción. [13]
Crítica
Tony Hoare dio una opinión contrastante sobre la seguridad del manejo de excepciones en 1980, describiendo que el lenguaje de programación Ada tiene "... una plétora de características y convenciones de notación, muchas de ellas innecesarias y algunas de ellas, como el manejo de excepciones, incluso peligroso. [...] No permita que este lenguaje en su estado actual se use en aplicaciones donde la confiabilidad es crítica [...]. El próximo cohete que se extravíe como resultado de un error en el lenguaje de programación puede no ser un exploratorio cohete espacial en un viaje inofensivo a Venus: puede ser una ojiva nuclear explotando sobre una de nuestras propias ciudades ". [15]
El manejo de excepciones a menudo no se maneja correctamente en el software, especialmente cuando hay múltiples fuentes de excepciones; El análisis del flujo de datos de 5 millones de líneas de código Java encontró más de 1300 defectos en el manejo de excepciones. [16] Citando múltiples estudios anteriores de otros (1999-2004) y sus propios resultados, Weimer y Necula escribieron que un problema significativo con excepciones es que "crean rutas de flujo de control ocultas que son difíciles de razonar para los programadores". [16] : 8:27
Go se lanzó inicialmente con el manejo de excepciones explícitamente omitido, y los desarrolladores argumentaron que ofuscaba el flujo de control . [17] Más tarde, se agregó el mecanismo de excepción panic
/ recover
al lenguaje, que los autores de Go recomiendan usar solo para errores irrecuperables que deberían detener todo el proceso. [18] [19] [20] [21]
Las excepciones, como el flujo no estructurado, aumentan el riesgo de fugas de recursos (como escapar de una sección bloqueada por un mutex o una que mantiene un archivo abierto temporalmente) o un estado incoherente. Existen varias técnicas para la gestión de recursos en presencia de excepciones, por lo general combinando el patrón de disposición con alguna forma de protección de desenrollado (como una finally
cláusula), que libera automáticamente el recurso cuando el control sale de una sección de código.
Soporte de excepción en lenguajes de programación
Muchos lenguajes de computadora tienen soporte integrado para excepciones y manejo de excepciones. Esto incluye ActionScript , Ada , BlitzMax , C ++ , C # , Clojure , COBOL , D , ECMAScript , Eiffel , Java , ML , Next Generation Shell , Object Pascal (por ejemplo , Delphi , Free Pascal y similares), PowerBuilder , Objective-C , OCaml , PHP (a partir de la versión 5), PL / I , PL / SQL , Prolog , Python , REALbasic , Ruby , Scala , Seed7 , Smalltalk , Tcl , Visual Prolog y la mayoría de los lenguajes .NET . El manejo de excepciones comúnmente no se puede reanudar en esos lenguajes, y cuando se lanza una excepción, el programa busca en la pila de llamadas a funciones hasta que se encuentra un controlador de excepciones.
Algunos idiomas exigen deshacer la pila a medida que avanza esta búsqueda. Es decir, si la función f , contiene un manejador H de excepción E , función de llamadas g , que a su vez llama a la función h , y una excepción E ocurre en h , luego funciona h y g puede terminarse, y H en f manejaré E .
Los lenguajes de manejo de excepciones sin este desenrollado son Common Lisp con su sistema de condiciones , PL / I y Smalltalk . Todos llaman al manejador de excepciones y no desenrollan la pila; sin embargo, en PL / I, si la "unidad ON" (manejador de excepciones) hace un GOTO fuera de la unidad ON, se desenrollará la pila. El controlador de excepciones tiene la opción de reiniciar el cálculo, reanudarlo o desconectarlo. Esto permite que el programa continúe el cálculo exactamente en el mismo lugar donde ocurrió el error (por ejemplo, cuando un archivo que faltaba anteriormente está disponible) o implementar notificaciones, registros, consultas y variables fluidas además del mecanismo de manejo de excepciones (como se hizo en Smalltalk). La implementación sin pila del lenguaje de programación Mythryl admite el manejo de excepciones en tiempo constante sin desenrollar la pila.
Excluyendo las diferencias sintácticas menores, solo hay un par de estilos de manejo de excepciones en uso. En el estilo más popular, una excepción se inicia mediante una declaración especial ( throw
o raise
) con un objeto de excepción (por ejemplo, con Java o Object Pascal) o un valor de un tipo enumerado extensible especial (por ejemplo, con Ada o SML). El alcance de controladores de excepciones comienza con una cláusula de marcador ( try
o arrancador bloque del lenguaje como begin
) y termina en el inicio de la primera cláusula controlador ( catch
, except
, rescue
). Pueden seguir varias cláusulas de controlador, y cada una puede especificar qué tipos de excepción maneja y qué nombre usa para el objeto de excepción.
Algunos lenguajes también permiten una cláusula ( else
) que se usa en caso de que no ocurra ninguna excepción antes de que se alcance el final del alcance del controlador.
Más común es una cláusula relacionada ( finally
o ensure
) que se ejecuta tanto si se produjo una excepción como si no, normalmente para liberar recursos adquiridos dentro del cuerpo del bloque de manejo de excepciones. En particular, C ++ no proporciona esta construcción, ya que fomenta la técnica de adquisición de recursos es inicialización (RAII) que libera recursos mediante destructores .
En su totalidad, el código de manejo de excepciones podría verse así (en pseudocódigo similar a Java ):
prueba { línea = consola . readLine (); if ( line . length () == 0 ) { throw new EmptyLineException ( "¡La línea leída desde la consola estaba vacía!" ); } consola . printLine ( "¡Hola% s!" % línea ); consola . printLine ( "El programa se ejecutó correctamente." ); } catch ( EmptyLineException e ) { consola . printLine ( "¡Hola!" ); } captura ( Excepción e ) { consola . printLine ( "Error:" + e . mensaje ()); } finalmente { consola . printLine ( "El programa está terminando." ); }
Como una variación menor, algunos lenguajes usan una cláusula de un solo controlador, que trata con la clase de la excepción internamente.
Según un artículo de 2008 de Westley Weimer y George Necula , la sintaxis de los try
... finally
bloques en Java es un factor que contribuye a los defectos del software. Cuando un método necesita manejar la adquisición y liberación de 3-5 recursos, los programadores aparentemente no están dispuestos a anidar suficientes bloques debido a problemas de legibilidad, incluso cuando esta sería una solución correcta. Es posible usar un solo bloque try
... finally
incluso cuando se trata de múltiples recursos, pero eso requiere un uso correcto de los valores centinela , que es otra fuente común de errores para este tipo de problemas. [16] : 8: 6–8: 7 Con respecto a la semántica del constructo try
... catch
... finally
en general, Weimer y Necula escriben que "Si bien try-catch-finalmente es conceptualmente simple, tiene la descripción de ejecución más complicada en la especificación del lenguaje [Gosling et al. 1996] y requiere cuatro niveles de "if" anidados en su descripción oficial en inglés. En resumen, contiene una gran cantidad de casos de esquina que los programadores a menudo pasan por alto ". [16] : 8: 13–8: 14
C admite varios medios de verificación de errores, pero generalmente no se considera que admita el "manejo de excepciones", aunque las funciones de biblioteca estándar setjmpylongjmp se pueden usar para implementar la semántica de excepciones.
Perl tiene soporte opcional para el manejo estructurado de excepciones.
El soporte de Python para el manejo de excepciones es generalizado y consistente. Es difícil escribir un programa Python robusto sin usar sus palabras clave try
y except
. [ cita requerida ]
Manejo de excepciones en jerarquías de UI
Los marcos web de front-end recientes, como React y Vue , han introducido mecanismos de manejo de errores en los que los errores se propagan hacia arriba en la jerarquía de componentes de la interfaz de usuario, de una manera análoga a cómo los errores se propagan por la pila de llamadas al ejecutar el código. [22] [23] Aquí, el mecanismo de límite de error sirve como análogo al mecanismo típico de intento-captura. Por lo tanto, un componente puede garantizar que los errores de sus componentes secundarios se detecten y manejen, y no se propaguen a los componentes principales.
Por ejemplo, en Vue, un componente detectaría errores al implementar errorCaptured
Vue . componente ( 'parent' , { template : ' ' , errorCaptured : ( err , vm , info ) => alert ( 'Se produjo un error' ); }) Vue . componente ( 'hijo' , { plantilla : ' {{cause_error ()}} ' })
Cuando se usa así en el marcado:
< padre > < hijo > hijo > padre >
El error producido por el componente hijo es detectado y manejado por el componente padre. [24]
Implementación de manejo de excepciones
La implementación del manejo de excepciones en lenguajes de programación generalmente implica una buena cantidad de soporte tanto de un generador de código como del sistema de tiempo de ejecución que acompaña al compilador. (Fue la adición del manejo de excepciones a C ++ lo que puso fin a la vida útil del compilador de C ++ original, Cfront . [25] ) Dos esquemas son los más comunes. El primero, el registro dinámico , genera código que actualiza continuamente las estructuras sobre el estado del programa en términos de manejo de excepciones. [26] Normalmente, esto agrega un nuevo elemento al diseño del marco de pila que sabe qué controladores están disponibles para la función o método asociado con ese marco; si se lanza una excepción, un puntero en el diseño dirige el tiempo de ejecución al código del controlador apropiado. Este enfoque es compacto en términos de espacio, pero agrega una sobrecarga de ejecución en la entrada y salida del marco. Se usó comúnmente en muchas implementaciones de Ada, por ejemplo, donde la generación compleja y el soporte de tiempo de ejecución ya eran necesarios para muchas otras características del lenguaje. El registro dinámico, que es bastante sencillo de definir, es susceptible de prueba de corrección . [27]
El segundo esquema, y el implementado en muchos compiladores de C ++ con calidad de producción, es un enfoque basado en tablas . Esto crea tablas estáticas en tiempo de compilación y tiempo de enlace que relacionan los rangos del contador del programa con el estado del programa con respecto al manejo de excepciones. [28] Luego, si se lanza una excepción, el sistema de tiempo de ejecución busca la ubicación de la instrucción actual en las tablas y determina qué controladores están en juego y qué se debe hacer. Este enfoque minimiza la sobrecarga ejecutiva para el caso en el que no se lanza una excepción. Esto sucede a costa de algo de espacio, pero este espacio se puede asignar en secciones de datos de solo lectura y con fines especiales que no se cargan ni se reubican hasta que se lanza una excepción. [29] Este segundo enfoque también es superior en términos de lograr seguridad en los subprocesos [ cita requerida ] .
También se han propuesto otros esquemas de definición y ejecución. [30] Para los lenguajes que admiten la metaprogramación , se han avanzado enfoques que no implican gastos generales (más allá del soporte ya presente para la reflexión ). [31]
Manejo de excepciones basado en diseño por contrato
Una visión diferente de las excepciones se basa en los principios del diseño por contrato y está respaldada en particular por el lenguaje Eiffel . La idea es proporcionar una base más rigurosa para el manejo de excepciones definiendo con precisión qué es comportamiento "normal" y "anormal". Específicamente, el enfoque se basa en dos conceptos:
- Incumplimiento : incapacidad de una operación para cumplir con su contrato. Por ejemplo, una suma puede producir un desbordamiento aritmético (no cumple su contrato de calcular una buena aproximación a la suma matemática); o una rutina puede no cumplir con su condición posterior.
- Excepción : un evento anormal que ocurre durante la ejecución de una rutina (esa rutina es el " receptor " de la excepción) durante su ejecución. Tal evento anormal es el resultado de la falla de una operación llamada por la rutina.
El "principio de manejo seguro de excepciones" introducido por Bertrand Meyer en la construcción de software orientado a objetos sostiene que solo hay dos formas significativas en que una rutina puede reaccionar cuando ocurre una excepción:
- Fallo o "pánico organizado": la rutina corrige el estado del objeto restableciendo el invariante (esta es la parte "organizada"), y luego falla (entra en pánico), lo que activa una excepción en su llamador (de modo que el evento anormal es no ignorado).
- Reintentar: la rutina vuelve a probar el algoritmo, generalmente después de cambiar algunos valores para que el próximo intento tenga más posibilidades de éxito.
En particular, no se permite simplemente ignorar una excepción; un bloque debe reintentarse y completarse con éxito, o propagar la excepción a su llamador.
A continuación se muestra un ejemplo expresado en sintaxis Eiffel. Se asume que una rutina send_fast
es normalmente la mejor manera de enviar un mensaje, pero puede fallar y desencadenar una excepción; si es así, el algoritmo se utiliza a continuación send_slow
, que fallará con menos frecuencia. Si send_slow
falla, la rutina send
en su conjunto debería fallar, lo que provocaría que la persona que llama obtenga una excepción.
enviar ( m : MENSAJE ) es : enviar m a través de un enlace rápido, si es posible, de lo contrario, a través de un enlace lento. local try_fast , try_slow : BOOLEAN do si intent_fast luego intent_slow : = Verdadero send_slow ( m ) else intent_fast : = Verdadero send_fast ( m ) finaliza el rescate si no intent_slow luego vuelve a intentar end end
Las variables locales booleanas se inicializan en False al principio. Si send_fast
falla, el cuerpo ( do
cláusula) se ejecutará nuevamente, provocando la ejecución de send_slow
. Si esta ejecución de send_slow
falla, la rescue
cláusula se ejecutará hasta el final sin retry
(sin else
cláusula en la final if
), provocando que la ejecución de la rutina en su conjunto falle.
Este enfoque tiene el mérito de definir claramente qué son los casos "normales" y "anormales": un caso anormal, que causa una excepción, es aquel en el que la rutina no puede cumplir con su contrato. Define una clara distribución de roles: la do
cláusula (cuerpo normal) se encarga de lograr, o intentar lograr, el contrato de la rutina; la rescue
cláusula se encarga de restablecer el contexto y reiniciar el proceso, si tiene alguna posibilidad de éxito, pero no de realizar ningún cálculo real.
Aunque las excepciones en Eiffel tienen una filosofía bastante clara, Kiniry (2006) critica su implementación porque "las excepciones que forman parte de la definición del lenguaje están representadas por valores INTEGER, las excepciones definidas por el desarrollador por valores STRING. [...] Además, porque son valores básicos y no objetos, no tienen una semántica inherente más allá de la que se expresa en una rutina auxiliar que necesariamente no puede ser infalible debido a la sobrecarga de representación en efecto (por ejemplo, no se pueden diferenciar dos números enteros del mismo valor) ". [7]
Excepciones no detectadas
Si se lanza una excepción y no se detecta (operativamente, se lanza una excepción cuando no hay un controlador aplicable especificado), la excepción no detectada es manejada por el tiempo de ejecución; la rutina que hace esto se llamacontrolador de excepciones no detectado . [32] [33] El comportamiento predeterminado más común es terminar el programa e imprimir un mensaje de error en la consola, que generalmente incluye información de depuración como una representación de cadena de la excepción y elseguimiento delapila. [32] [34] [35] Esto a menudo se evita al tener un controlador de nivel superior (nivel de aplicación) (por ejemplo, en unbucle de eventos) que detecta las excepciones antes de que lleguen al tiempo de ejecución. [32] [36]
Tenga en cuenta que, aunque una excepción no detectada puede provocar que el programa finalice de forma anormal (es posible que el programa no sea correcto si no se detecta una excepción, en particular al no revertir transacciones parcialmente completadas o al no liberar recursos), el proceso finaliza normalmente (asumiendo el runtime funciona correctamente), ya que el runtime (que controla la ejecución del programa) puede garantizar el cierre ordenado del proceso.
En un programa multiproceso, una excepción no detectada en un subproceso puede resultar en la terminación de solo ese subproceso, no de todo el proceso (las excepciones no detectadas en el controlador de nivel de subproceso son capturadas por el controlador de nivel superior). Esto es particularmente importante para los servidores, donde, por ejemplo, un servlet (que se ejecuta en su propio hilo) puede terminarse sin que el servidor se vea afectado en general.
Este controlador de excepciones no detectado predeterminado puede anularse, ya sea globalmente o por subproceso, por ejemplo, para proporcionar un registro alternativo o informes de usuario final de excepciones no detectadas, o para reiniciar subprocesos que terminan debido a una excepción no detectada. Por ejemplo, en Java esto se hace para un solo hilo vía Thread.setUncaughtExceptionHandler
y globalmente vía Thread.setDefaultUncaughtExceptionHandler
; en Python esto se hace modificando sys.excepthook
.
Comprobación estática de excepciones
Excepciones marcadas
Los diseñadores de Java idearon [37] excepciones comprobadas, [38] que son un conjunto especial de excepciones. Las excepciones marcadas que puede generar un método son parte de la firma del método . Por ejemplo, si un método puede lanzar un IOException
, debe declarar este hecho explícitamente en la firma de su método. No hacerlo genera un error en tiempo de compilación.
Kiniry (2006) señala, sin embargo, que las bibliotecas de Java (como lo eran en 2006) a menudo eran inconsistentes en su enfoque para la notificación de errores, porque "No todas las situaciones erróneas en Java están representadas por excepciones. Muchos métodos devuelven valores especiales que indican fallas codificadas como campo constante de clases relacionadas ". [7]
Las excepciones marcadas están relacionadas con los verificadores de excepciones que existen para el lenguaje de programación OCaml . [39] La herramienta externa para OCaml es invisible (es decir, no requiere anotaciones sintácticas) y opcional (es decir, es posible compilar y ejecutar un programa sin haber verificado las excepciones, aunque esto no se recomienda para código de producción).
El lenguaje de programación CLU tenía una característica con la interfaz más cercana a lo que Java introdujo más tarde. Una función podría generar solo las excepciones enumeradas en su tipo, pero cualquier excepción con fugas de las funciones llamadas se convertiría automáticamente en la única excepción de tiempo de ejecución failure
, en lugar de resultar en un error de tiempo de compilación. Más tarde, Modula-3 tuvo una característica similar. [40] Estas características no incluyen la comprobación del tiempo de compilación que es fundamental en el concepto de excepciones comprobadas, y no se ha incorporado (a partir de 2006) a los principales lenguajes de programación distintos de Java. [41]
Las primeras versiones del lenguaje de programación C ++ incluían un mecanismo opcional para las excepciones comprobadas, llamadas especificaciones de excepción . Por defecto, cualquier función podría lanzar cualquier excepción, pero esto podría estar limitado por una throw
cláusula agregada a la firma de la función, que especifique qué excepciones puede generar la función. Las especificaciones de excepción no se hicieron cumplir en tiempo de compilación. Las violaciones dieron como resultado la llamada a la función global . [42] Se podría dar una especificación de excepción vacía, que indica que la función no lanzará ninguna excepción. Esto no se estableció por defecto cuando se agregó el manejo de excepciones al lenguaje porque habría requerido demasiada modificación del código existente, habría impedido la interacción con el código escrito en otros lenguajes y habría tentado a los programadores a escribir demasiados controladores en el local. nivel. [42] Sin embargo, el uso explícito de especificaciones de excepción vacías podría permitir que los compiladores de C ++ realicen optimizaciones significativas de diseño de código y pila que se excluyen cuando el manejo de excepciones puede tener lugar en una función. [29] Algunos analistas consideraron que el uso adecuado de las especificaciones de excepción en C ++ era difícil de lograr. [43] Este uso de especificaciones de excepción se incluyó en C ++ 03 , en desuso en el estándar de lenguaje C ++ de 2012 ( C ++ 11 ), [44] y se eliminó del lenguaje en C ++ 17 . Una función que no arrojará ninguna excepción ahora se puede denotar con la palabra clave.std::unexpected
noexcept
A diferencia de Java, lenguajes como C # no requieren declaración de ningún tipo de excepción. Según Hanspeter Mössenböck, no distinguir entre excepciones para ser llamadas (marcadas) y excepciones para no ser llamadas (no marcadas) hace que el programa escrito sea más conveniente, pero menos robusto, ya que una excepción no detectada da como resultado un aborto con una seguimiento de pila . [45] Kiniry (2006) señala, sin embargo, que el JDK de Java (versión 1.4.1) arroja una gran cantidad de excepciones no comprobadas: una por cada 140 líneas de código, mientras que Eiffel las usa con mucha más moderación, con una lanzada cada 4,600 líneas de código. . Kiniry también escribe que "Como cualquier programador de Java sabe, el volumen de try catch
código en una aplicación Java típica es a veces mayor que el código comparable necesario para la comprobación explícita de parámetros formales y valores de retorno en otros lenguajes que no tienen excepciones comprobadas. El consenso general entre los programadores de Java en las trincheras es que tratar con excepciones comprobadas es una tarea casi tan desagradable como escribir documentación. Por lo tanto, muchos programadores informan que "resienten" las excepciones comprobadas. Esto conduce a una abundancia de excepciones comprobadas pero ignoradas excepciones ". [7] Kiniry también señala que los desarrolladores de C # aparentemente fueron influenciados por este tipo de experiencias de usuario, y se les atribuye la siguiente cita (a través de Eric Gunnerson):
"El examen de programas pequeños lleva a la conclusión de que requerir especificaciones de excepción podría mejorar la productividad del desarrollador y mejorar la calidad del código, pero la experiencia con grandes proyectos de software sugiere un resultado diferente: menor productividad y poco o ningún aumento en la calidad del código". [7]
Según Anders Hejlsberg, hubo un acuerdo bastante amplio en su grupo de diseño de no haber verificado las excepciones como característica del lenguaje en C #. Hejlsberg explicó en una entrevista que
“La cláusula throws, al menos la forma en que se implementa en Java, no necesariamente te obliga a manejar las excepciones, pero si no las manejas, te obliga a reconocer con precisión qué excepciones podrían pasar. Requiere que usted capture las excepciones declaradas o las ponga en su propia cláusula throws. Para evitar este requisito, la gente hace cosas ridículas. Por ejemplo, decoran todos los métodos con "arroja Excepción". Eso simplemente anula por completo la función, y acaba de hacer que el programador escriba más basura. Eso no ayuda a nadie ". [46]
Vistas sobre el uso
Las excepciones marcadas pueden, en tiempo de compilación , reducir la incidencia de excepciones no controladas que surgen en tiempo de ejecución en una aplicación determinada. Las excepciones no controladas (como los objetos JavaRuntimeException
y Error
) permanecen sin controlar.
Sin embargo, las excepciones comprobadas pueden requerir throws
declaraciones extensas , que revelen detalles de implementación y reduzcan la encapsulación , o fomentar la codificación de bloques mal considerados que pueden ocultar excepciones legítimas de sus manejadores apropiados. [ cita requerida ] Considere una base de código creciente con el tiempo. Se puede declarar una interfaz para lanzar excepciones X e Y. En una versión posterior del código, si uno quiere lanzar la excepción Z, haría que el nuevo código sea incompatible con los usos anteriores. Además, con el patrón de adaptador , en el que un cuerpo de código declara una interfaz que luego es implementada por un cuerpo de código diferente para que el código pueda ser conectado y llamado por el primero, el código del adaptador puede tener un rico conjunto de excepciones para describe problemas, pero se ve obligado a utilizar los tipos de excepción declarados en la interfaz.try/catch
Es posible reducir el número de excepciones declaradas ya sea declarando una superclase de todas las excepciones potencialmente lanzadas, o definiendo y declarando tipos de excepción que sean adecuados para el nivel de abstracción del método llamado [47] y mapeando excepciones de nivel inferior a estas tipos, preferiblemente envueltos usando el encadenamiento de excepciones para preservar la causa raíz. Además, es muy posible que en el ejemplo anterior de la interfaz cambiante, el código de llamada también deba modificarse, ya que, en cierto sentido, las excepciones que puede generar un método son parte de la interfaz implícita del método de todos modos.
El uso de una declaración o suele ser suficiente para satisfacer la comprobación en Java. Si bien esto puede tener algún uso, esencialmente elude el mecanismo de excepción verificado, que Oracle desaconseja. [48]throws Exception
catch (Exception e)
Los tipos de excepción no marcados generalmente no deben manejarse, excepto posiblemente en los niveles más externos del alcance. Estos a menudo representan situaciones que no permiten la recuperación: RuntimeException
s con frecuencia reflejan los defectos de programación, [49] y Error
s representan generalmente fracasos JVM irrecuperables. Incluso en un lenguaje que admite excepciones marcadas, hay casos en los que el uso de excepciones marcadas no es apropiado. [50]
Comprobación dinámica de excepciones
El punto de las rutinas de manejo de excepciones es garantizar que el código pueda manejar condiciones de error. Para establecer que las rutinas de manejo de excepciones son lo suficientemente sólidas, es necesario presentar el código con un amplio espectro de entradas no válidas o inesperadas, como las que se pueden crear mediante la inyección de fallas de software y las pruebas de mutación (que a veces también se denomina fuzz pruebas ). Uno de los tipos de software más difíciles para el cual escribir rutinas de manejo de excepciones es el software de protocolo, ya que se debe preparar una implementación de protocolo robusta para recibir entradas que no cumplan con las especificaciones relevantes.
Para garantizar que se pueda realizar un análisis de regresión significativo a lo largo de un proceso de ciclo de vida de desarrollo de software , cualquier prueba de manejo de excepciones debe estar altamente automatizada y los casos de prueba deben generarse de manera científica y repetible. Existen varios sistemas disponibles comercialmente que realizan tales pruebas.
En entornos de motor en tiempo de ejecución como Java o .NET , existen herramientas que se adjuntan al motor en tiempo de ejecución y cada vez que ocurre una excepción de interés, registran la información de depuración que existía en la memoria en el momento en que se lanzó la excepción ( pila de llamadas y montón valores). Estas herramientas se denominan herramientas de interceptación de errores o manejo de excepciones automatizadas y proporcionan información sobre la "causa raíz" de las excepciones.
Sincronicidad de excepciones
Algo relacionado con el concepto de excepciones comprobadas es la sincronicidad de excepciones . Las excepciones sincrónicas ocurren en una declaración de programa específica, mientras que las excepciones asincrónicas pueden surgir prácticamente en cualquier lugar. [51] [52] De ello se deduce que el compilador no puede exigir el manejo asincrónico de excepciones. También son difíciles de programar. Ejemplos de eventos naturalmente asincrónicos incluyen presionar Ctrl-C para interrumpir un programa y recibir una señal como "detener" o "suspender" de otro hilo de ejecución .
Los lenguajes de programación suelen lidiar con esto limitando la asincronicidad, por ejemplo, Java ha desaprobado el uso de su excepción ThreadDeath que se usó para permitir que un hilo detenga otro. [53] En cambio, puede haber excepciones semi-asincrónicas que solo surgen en ubicaciones adecuadas del programa o de forma sincrónica.
Sistemas de condición
Common Lisp , Dylan y Smalltalk tienen un sistema de condición [54] (ver Common Lisp Condition System ) que abarca los sistemas de manejo de excepciones antes mencionados. En esos lenguajes o entornos, el advenimiento de una condición (una "generalización de un error" según Kent Pitman ) implica una llamada de función, y solo tarde en el manejador de excepciones se puede tomar la decisión de deshacer la pila.
Las condiciones son una generalización de excepciones. Cuando surge una condición, se busca y selecciona un manejador de condición apropiado, en orden de pila, para manejar la condición. Las condiciones que no representan errores pueden no ser manejadas con seguridad por completo; su único propósito puede ser propagar sugerencias o advertencias hacia el usuario. [55]
Excepciones continuas
Esto está relacionado con el llamado modelo de reanudación del manejo de excepciones, en el que se dice que algunas excepciones son continuables : se permite volver a la expresión que señaló una excepción, después de haber tomado una acción correctiva en el manejador. El sistema de condiciones se generaliza así: dentro del controlador de una condición no grave (también conocida como excepción continuable ), es posible saltar a puntos de reinicio predefinidos (también conocidos como reinicios ) que se encuentran entre la expresión de señalización y el controlador de condición. Los reinicios son funciones cerradas sobre algún entorno léxico, lo que permite al programador reparar este entorno antes de salir del controlador de condiciones por completo o desenrollar la pila, incluso parcialmente.
Un ejemplo es la condición ENDPAGE en PL / I; la unidad ON puede escribir líneas de avance de página y líneas de encabezado para la página siguiente, luego pasar para reanudar la ejecución del código interrumpido.
Reinicia un mecanismo separado de la política
Además, el manejo de condiciones proporciona una separación entre el mecanismo y la política . Los reinicios proporcionan varios mecanismos posibles para recuperarse de un error, pero no seleccionan qué mecanismo es apropiado en una situación determinada. Esa es la provincia del controlador de condiciones, que (dado que se encuentra en un código de nivel superior) tiene acceso a una vista más amplia.
Un ejemplo: suponga que hay una función de biblioteca cuyo propósito es analizar una sola entrada de archivo syslog . ¿Qué debe hacer esta función si la entrada está mal formada? No hay una respuesta correcta, porque la misma biblioteca podría implementarse en programas para muchos propósitos diferentes. En un navegador de archivos de registro interactivo, lo correcto podría ser devolver la entrada sin analizar, para que el usuario pueda verla, pero en un programa automatizado de resumen de registros, lo correcto podría ser proporcionar valores nulos para el campos ilegibles, pero abortar con un error, si demasiadas entradas tienen un formato incorrecto.
Es decir, la pregunta sólo puede responderse en términos de los objetivos más amplios del programa, que no son conocidos por la función de biblioteca de propósito general. No obstante, salir con un mensaje de error rara vez es la respuesta correcta. Entonces, en lugar de simplemente salir con un error, la función puede establecer reinicios que ofrecen varias formas de continuar, por ejemplo, omitir la entrada del registro, proporcionar valores predeterminados o nulos para los campos ilegibles, preguntar al usuario los valores faltantes o para desenrollar la pila y cancelar el procesamiento con un mensaje de error. Los reinicios ofrecidos constituyen los mecanismos disponibles para recuperarse de un error; la selección de reinicio por parte del manejador de condiciones proporciona la política .
Ver también
- Sintaxis de manejo de excepciones
- Manejo automatizado de excepciones
- Seguridad de excepción
- Continuación
- Programación defensiva
- setjmp / longjmp
- Triple culpa
- Manejo de excepciones vectoriales (VEH)
- Tipos de opciones y tipos de resultados , formas alternativas de manejar errores en la programación funcional sin excepciones
- Trampa (informática)
Referencias
- ^ "Detección de excepciones de hardware" . INSTRUMENTOS TEXAS. 2011-11-24. Archivado desde el original el 10 de noviembre de 2013 . Consultado el 5 de octubre de 2012 .
- ^ a b Xiaoye Li ; James Demmel (1994). "Algoritmos numéricos más rápidos a través del manejo de excepciones, transacciones IEEE en computadoras, 43 (8)": 983–992. Cite journal requiere
|journal=
( ayuda ) - ^ a b c W.Kahan (5 de julio de 2005). "Una demostración de la presustitución de ∞ / ∞" (PDF) . Archivado (PDF) desde el original el 10 de marzo de 2012.
- ^ John Hauser (1996). "Manejo de excepciones de punto flotante en programas numéricos, transacciones ACM en lenguajes de programación y sistemas 18 (2)": 139-174. Cite journal requiere
|journal=
( ayuda ) - ^ "Las lecciones de Ariane" . www.irisa.fr . Archivado desde el original el 4 de junio de 2016 . Consultado el 5 de mayo de 2018 .
- ^ "Fallo ARIANE 5 - Informe completo" . Archivado desde el original el 26 de abril de 2014 . Consultado el 16 de julio de 2014 .
- ^ a b c d e f Kiniry, JR (2006). "Excepciones en Java y Eiffel: dos extremos en el diseño y la aplicación de excepciones". Temas avanzados en técnicas de manejo de excepciones . Apuntes de conferencias en informática. 4119 . págs. 288–300. doi : 10.1007 / 11818502_16 . ISBN 978-3-540-37443-5.
- ^ "Stroustrup: Preguntas frecuentes sobre estilo y técnica de C ++" . www.stroustrup.com . Archivado desde el original el 2 de febrero de 2018 . Consultado el 5 de mayo de 2018 .
- ^ Bloch, Joshua (2008). "Ítem 57: Use excepciones solo para situaciones excepcionales" . Eficaz Java (segunda edición) . Addison-Wesley. pag. 241 . ISBN 978-0-321-35668-0.
- ^ Se manejan todas las excepciones, Jim Wilcox, "Se manejan todas las excepciones" . Archivado desde el original el 18 de marzo de 2015 . Consultado el 8 de diciembre de 2014 .
- ↑ a b Gabriel y Steele , 2008 , p. 3.
- ^ White 1979 , p. 194.
- ↑ a b Stroustrup , 1994 , p. 392.
- ^ a b Stroustrup 1994 , 16.6 Manejo de excepciones: reanudación frente a rescisión, págs. 390–393.
- ^ COCHE Hoare. "La ropa vieja del emperador". Conferencia del Premio Turing de 1980
- ^ a b c d Weimer, W; Necula, GC (2008). "Situaciones excepcionales y confiabilidad del programa" (PDF) . Transacciones ACM sobre lenguajes y sistemas de programación . 30 (2). Archivado (PDF) desde el original el 23 de septiembre de 2015.
- ^ "Preguntas frecuentes" . Archivado desde el original el 3 de mayo de 2017 . Consultado el 27 de abril de 2017 .
Creemos que acoplar excepciones a una estructura de control, como en el idioma try-catch-finalmente, da como resultado un código complicado. También tiende a alentar a los programadores a etiquetar demasiados errores comunes, como no abrir un archivo, como excepcionales.
- ^ Pánico y recuperación Archivado el 24 de octubre de 2013 en Wayback Machine , Go wiki
- ^ "Historial de instantáneas semanal" . golang.org . Archivado desde el original el 3 de abril de 2017.
- ^ "Propuesta de un mecanismo similar a una excepción" . nueces de golang . 25 de marzo de 2010 . Consultado el 25 de marzo de 2010 .
- ^ "Go eficaz" . golang.org . Archivado desde el original el 6 de enero de 2015.
- ^ "Límites de error" . Reaccionar . Consultado el 10 de diciembre de 2018 .
- ^ "API de Vue.js" . Vue.js . Consultado el 10 de diciembre de 2018 .
- ^ "Manejo de errores con Vue.js" . CatchJS . Consultado el 10 de diciembre de 2018 .
- ^ Scott Meyers , el software C ++ más importante ... Archivado el 28 de abril de 2011en la Wayback Machine , 2006
- ^ D. Cameron, P. Faust, D. Lenkov, M. Mehta, "Una implementación portátil del manejo de excepciones de C ++", Actas de la Conferencia de C ++ (agosto de 1992) USENIX .
- ^ Graham Hutton, Joel Wright, " Compilación de excepciones correctamente archivada el 11 de septiembre de 2014 en la Wayback Machine ". Actas de la 7ma Conferencia Internacional sobre Matemáticas de Construcción de Programas , 2004.
- ^ Lajoie, Josée (marzo-abril de 1994). "Manejo de excepciones: apoyo al mecanismo de ejecución". Informe C ++ . 6 (3).
- ^ a b Schilling, Jonathan L. (agosto de 1998). "Optimización del manejo de excepciones de C ++". Avisos SIGPLAN . 33 (8): 40–47. doi : 10.1145 / 286385.286390 . S2CID 1522664 .
- ^ " "Copia archivada" . Archivado desde el original el 1 de enero de 2012 . Consultado el 27 de febrero de 2012 .Mantenimiento de CS1: copia archivada como título ( enlace )", Corporación Intel .
- ^ M. Hof, H. Mössenböck, P. Pirkelbauer, " Manejo de excepciones con cero sobrecarga mediante metaprogramación archivado el 3 de marzo de 2016 en Wayback Machine ", Actas SOFSEM'97 , noviembre de 1997, Notas de la conferencia en Ciencias de la Computación 1338 , págs. 423-431.
- ^ a b c Biblioteca de desarrolladores de Mac , " Excepciones no detectadas archivadas el 4 de marzo de 2016 en Wayback Machine "
- ^ MSDN , Evento AppDomain.UnhandledException Archivado 2016-03-04 en Wayback Machine
- ^ El tutorial de Python , " 8. Errores y excepciones archivados el 1 de septiembre de 2015 en la Wayback Machine "
- ^ "Prácticas de Java -> Proporcionar un controlador de excepciones no detectado" . www.javapractices.com . Archivado desde el original el 9 de septiembre de 2016 . Consultado el 5 de mayo de 2018 .
- ^ PyMOTW (módulo de Python de la semana), " Manejo de excepciones archivado el 15 de septiembre de 2015en Wayback Machine "
- ^ "Google Answers: El origen de las excepciones comprobadas" . Archivado desde el original el 6 de agosto de 2011 . Consultado el 15 de diciembre de 2011 .
- ^ Especificación del lenguaje Java, capítulo 11.2. http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html#11.2 Archivado el 8 de diciembre de 2006 en la Wayback Machine.
- ^ "OcamlExc - Un analizador de excepciones no detectado para Objective Caml" . Caml.inria.fr. Archivado desde el original el 6 de agosto de 2011 . Consultado el 15 de diciembre de 2011 .
- ^ "Modula-3 - Tipos de procedimientos" . .cs.columbia.edu. 1995-03-08. Archivado desde el original el 9 de mayo de 2008 . Consultado el 15 de diciembre de 2011 .
- ^ "MindView, Inc de Bruce Eckel: ¿Java necesita excepciones marcadas?" . Mindview.net. Archivado desde el original el 5 de abril de 2002 . Consultado el 15 de diciembre de 2011 .
- ^ a b Bjarne Stroustrup , Tercera edición del lenguaje de programación C ++ , Addison Wesley , 1997. ISBN 0-201-88954-4 . págs. 375-380.
- ^ Reeves, JW (julio de 1996). "Diez directrices para las especificaciones de excepción". Informe C ++ . 8 (7).
- ^ Sutter, Herb (3 de marzo de 2010). "Informe de viaje: reunión de normas ISO C ++ de marzo de 2010" . Archivado desde el original el 23 de marzo de 2010 . Consultado el 24 de marzo de 2010 .
- ^ Mössenböck, Hanspeter (25 de marzo de 2002). "C # avanzado: número variable de parámetros" (PDF) . http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/ : Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. pag. 32. Archivado (PDF) desde el original el 20 de septiembre de 2011 . Consultado el 5 de agosto de 2011 .
- ^ Bill Venners; Bruce Eckel (18 de agosto de 2003). "El problema con las excepciones marcadas: una conversación con Anders Hejlsberg, parte II" . pag. 2 . Archivado desde el original el 18 de febrero de 2015.
- ^ Bloch 2001: 178 Bloch, Joshua (2001). Guía eficaz del lenguaje de programación Java . Addison-Wesley Professional. ISBN 978-0-201-31005-4.
- ^ "Ventajas de las excepciones (los tutoriales de Java ™: clases esenciales: excepciones)" . Download.oracle.com. Archivado desde el original el 26 de octubre de 2011 . Consultado el 15 de diciembre de 2011 .
- ^ Bloch 2001: 172
- ^ "Excepciones no comprobadas: la controversia (tutoriales de Java ™: clases esenciales: excepciones)" . Download.oracle.com. Archivado desde el original el 17 de noviembre de 2011 . Consultado el 15 de diciembre de 2011 .
- ^ "Excepciones asincrónicas en Haskell - Marlow, Jones, Moran (ResearchIndex)" . Citeseer.ist.psu.edu. Archivado desde el original el 23 de febrero de 2011 . Consultado el 15 de diciembre de 2011 .
- ^ Excepciones asincrónicas seguras para Python. "Copia archivada" . Archivado desde el original el 30 de agosto de 2006 . Consultado el 7 de diciembre de 2006 .Mantenimiento de CS1: copia archivada como título ( enlace )
- ^ "Desactivación primitiva de subprocesos de Java" . Java.sun.com. Archivado desde el original el 26 de abril de 2009 . Consultado el 15 de diciembre de 2011 .
- ^ De qué se tratan realmente las condiciones (excepciones) (2008-03-24). "De qué se tratan realmente las condiciones (excepciones)" . Danweinreb.org. Archivado desde el original el 1 de febrero de 2013 . Consultado el 18 de septiembre de 2014 .
- ^ "Conceptos del sistema de condiciones" . Franz.com. 2009-07-21. Archivado desde el original el 28 de junio de 2007 . Consultado el 15 de diciembre de 2011 .
- Gabriel, Richard P .; Steele, Guy L. (2008). Un patrón de evolución del lenguaje (PDF) . LISP50: Celebrando el 50 aniversario de Lisp. págs. 1-10. doi : 10.1145 / 1529966.1529967 . ISBN 978-1-60558-383-9.
- Goodenough, John B. (1975a). Manejo estructurado de excepciones . Actas del 2º simposio ACM SIGACT-SIGPLAN sobre Principios de lenguajes de programación - POPL '75. págs. 204–224. doi : 10.1145 / 512976.512997 .
- Goodenough, John B. (1975). "Manejo de excepciones: problemas y una notación propuesta" (PDF) . Comunicaciones de la ACM . 18 (12): 683–696. CiteSeerX 10.1.1.122.7791 . doi : 10.1145 / 361227.361230 . S2CID 12935051 .
- White, Jon L (mayo de 1979). NIL - Una perspectiva (PDF) . Actas de la Conferencia de usuarios de Macsyma de 1979.
enlaces externos
- Un curso intensivo sobre las profundidades del manejo de excepciones estructuradas de Win32 por Matt Pietrek - Microsoft Systems Journal (1997)
- Artículo " Manejo de excepciones C ++ " por Christophe de Dinechin
- Artículo " Prácticas excepcionales " de Brian Goetz
- Artículo " Manejo de excepciones orientado a objetos en Perl " por Arun Udaya Shankar
- Artículo " Programación con excepciones en C ++ " por Kyle Loudon
- Artículo " Excepciones no controladas: la controversia "
- Diapositivas de la conferencia Políticas de manejo de excepciones de punto flotante (pdf p. 46) por William Kahan
- Descripciones del repositorio de patrones de Portland
- ¿Java necesita excepciones marcadas?