La sintaxis de manejo de excepciones es el conjunto de palabras clave y/o estructuras proporcionadas por un lenguaje de programación informática para permitir el manejo de excepciones , que separa el manejo de errores que surgen durante la operación de un programa de sus procesos ordinarios. La sintaxis para el manejo de excepciones varía entre lenguajes de programación , en parte para cubrir diferencias semánticas, pero en gran medida para adaptarse a la estructura sintáctica general de cada lenguaje . Algunos lenguajes no llaman al concepto relevante " manejo de excepciones "; otros pueden no tener facilidades directas para ello, pero aún pueden proporcionar medios para implementarlo.
Lo más común es que el manejo de errores utilice un try...[catch...][finally...]
bloque y los errores se creen mediante una throw
declaración, pero existe una variación significativa en los nombres y la sintaxis.
Some_Error : excepción ;
generar Some_Error ;genera Some_Error con "Memoria insuficiente" ; -- mensaje de diagnóstico específico
con Ada.Exceptions , Ada .Text_IO ;procedimiento Foo es Some_Error : excepción ; comienzo Do_Something_Interesting ; excepción -- Inicio de manejadores de excepciones cuando Constraint_Error => ... -- Manejar error de restricción cuando Storage_Error => -- Propagar Storage_Error como una excepción diferente con un mensaje útil levantar Some_Error con "Fuera de memoria" ; cuando Error : otros => -- Manejar todos los demás Ada . Text_IO . Put ( "Excepción: " ); Ada . Text_IO . Put_Line ( Ada . Exceptions . Exception_Name ( Error )); Ada . Text_IO . Put_Line ( Ada . Exceptions . Exception_Message ( Error )); fin Foo ;
La mayoría de los lenguajes ensambladores tendrán una instrucción macro o una dirección de interrupción disponible para el sistema en particular para interceptar eventos como códigos de operación ilegales, verificación de programa, errores de datos, desbordamiento, división por cero y otros similares. Los mainframes IBM y Univac tenían la macro STXIT . Los sistemas RT11 de Digital Equipment Corporation tenían vectores de trampa para errores de programa, interrupciones de E/S y similares. DOS tiene ciertas direcciones de interrupción. Microsoft Windows tiene llamadas de módulo específicas para atrapar errores de programa.
excepción MyException de ( string , int ) (*las excepciones pueden llevar un valor*)implementar main0 () : void = try $ raise MyException ( "no hay suficiente comida" , 2 ) con | ~ MyException ( s , i ) => begin $ extfcall ( void , "fprintf" , stderr_ref , "%s: %d" , s , i ); fileref_close ( stderr_ref ); end
#!/usr/bin/env bash #set -e proporciona otro mecanismo de error
print_error (){ echo "hubo un error" } trap print_error exit #list señales a trap tempfile = ` mktemp ` trap "rm $tempfile " exit
./other.sh || echo advertencia: otro falló echo oops ) echo nunca se imprimió
Se puede configurar una trampa para múltiples errores, respondiendo a cualquier señal con una sintaxis como la siguiente:
trap 'echo Error at line ${LINENO}' ERR
En BASIC se utiliza una estructura goto/gosub On Error y es bastante diferente del manejo de excepciones moderno; en BASIC solo hay un controlador global mientras que en el manejo de excepciones moderno, los controladores de excepciones se apilan.
EN CASO DE ERROR, GOTO, controlador ABRIR "Somefile.txt" PARA ENTRADA COMO # 1 CERRAR # 1 IMPRIMIR "Archivo abierto correctamente" FIN manejador: PRINT "El archivo no existe" END ' RESUME se puede utilizar en su lugar, lo que devuelve el control a la posición original.
C no proporciona soporte directo para el manejo de excepciones: es responsabilidad del programador prevenir errores en primer lugar y probar los valores de retorno de las funciones.
En cualquier caso, una forma posible de implementar el manejo de excepciones en C estándar es utilizar las funciones setjmp/longjmp :
#incluir <setjmp.h> #incluir <stdio.h> #incluir <stdlib.h> enum { SOME_EXCEPTION = 1 } excepción ; jmp_buf estado ; int main ( void ) { if ( ! setjmp ( state )) // try { if ( /* sucedió algo */ ) { excepción = ALGUNA_EXCEPCIÓN ; longjmp ( state , 0 ); // lanzar ALGUNA_EXCEPCIÓN } } else switch ( exception ) { case ALGUNA_EXCEPCIÓN : // atrapar ALGUNA_EXCEPCIÓN puts ( "ALGUNA_EXCEPCIÓN atrapada" ); break ; default : // atrapar ... puts ( "Alguna excepción extraña" ); } return EXIT_SUCCESS ; }
Existen dos tipos:
Ejemplo de SEH en lenguaje de programación C:
int filterExpression ( EXCEPTION_POINTERS * ep ) { ep -> ContextRecord -> Eip += 8 ; // la instrucción de división puede codificarse de 2 a 8 bytes return EXCEPTION_CONTINUE_EXECUTION ; } int main ( void ) { static int zero ; __try { zero = 1 / zero ; __asm { nop nop nop nop nop nop nop nop } printf ( "Más allá de la excepción. \n " ); } __except ( filterExpression ( GetExceptionInformation ())) { printf ( "Manejador llamado. \n " ); } return 0 ; }
Un try
bloque debe tener al menos una cláusula catch
or finally
y como máximo una finally
cláusula.
public static void Main () { try { // Código que podría generar una excepción. } catch ( HttpException ex ) { // Maneja una HttpException. El objeto de excepción se almacena en "ex". } catch ( Exception ) { // Maneja cualquier excepción CLR que no sea una HttpException. // Dado que a la excepción no se le ha dado un identificador, no se puede hacer referencia a ella. } catch { // Maneja cualquier cosa que pueda generarse, incluidas las excepciones que no sean CLR. } finally { // Siempre se ejecuta al salir del bloque try (incluidas las cláusulas catch), independientemente de si se generaron excepciones o si se manejaron. // A menudo se usa para limpiar y cerrar recursos que maneja un archivo de este tipo. // No se puede ejecutar cuando se llama a Environment.FailFast() y en otras condiciones excepcionales de todo el sistema (por ejemplo, pérdida de energía), o cuando el proceso falla debido a una excepción en otro hilo. } }
#include <exception> int main () { try { // hacer algo (podría generar una excepción) } catch ( const std :: exception & e ) { // manejar la excepción e } catch (...) { // captura todas las excepciones, no capturadas previamente por un bloque catch // se puede usar para capturar excepciones de tipo desconocido o irrelevante } }
En C++, se puede utilizar una técnica de adquisición de recursos para inicializarlos en situaciones excepcionales. C++ no admite intencionadamente finally
. [1] Las llaves externas del método son opcionales.
< cfscript > try { //throw CF9+ throw ( type = "TypeOfException" , message = "Oops" , detail = "xyz" ); // sintaxis de lanzamiento alternativa: throw "Oops" ; // esto es equivalente al valor "message" en el ejemplo anterior } catch ( any e ) { writeOutput ( "Error: " & e . message ); rethrow ; //CF9+ } finally { //CF9+ writeOutput ( "Ejecuto incluso si no hay error" ); } < /cfscript>
Documentación de Adobe ColdFusion [2]
<Intenta> código que puede causar una excepción <cfcatch ... > <cftry> Primer nivel de código de manejo de excepciones <cfcatch ... > Segundo nivel de código de manejo de excepciones </cfcatch> < cffinalmente > código final </ cffinalmente > < / cftry> </ cfcatch> </ cftry>
Documentación de Adobe ColdFusion [3]
Además de la sintaxis estándar anterior, los dialectos CFML de Railo y Lucee permiten una retry
declaración. [4]
Esta declaración devuelve el procesamiento al inicio del try
bloque anterior.
Ejemplo de CFScript:
try { // código que podría resultar en una excepción } catch ( cualquier e ){ reintentar ; }
Ejemplo de sintaxis de etiqueta:
<Intenta><!--- código que podría generar una excepción ---><cfcatch> < cfretry > </cfcatch> </cftry>
import std . stdio ; // para writefln() int main () { try { // hacer algo que pueda generar una excepción } catch ( FooException e ) { // manejar excepciones de tipo FooException } catch ( Object o ) { // manejar cualquier otra excepción writefln ( "Excepción no controlada: " , o ); return 1 ; } return 0 ; }
En D, una finally
cláusula o técnica de inicialización de adquisición de recursos se puede utilizar para limpiar recursos en situaciones excepcionales.
tipo ECustom = clase ( Excepción ) // Las excepciones son hijos de la clase Excepción. privado FCustomData : SomeType ; // Las excepciones pueden tener extensiones personalizadas. público constructor CreateCustom ( Data : SomeType ) ; // Necesita una propiedad de implementación CustomData : SomeType leer FCustomData ; fin ;
generar excepción.Crear ( ' Mensaje ' ) ; generar una excepción . CreateFmt ( 'Mensaje con valores: %d, %d' , [ valor1 , valor2 ]) ; // Consulte SysUtils.Format() para conocer los parámetros. generar ECustom .CreateCustom ( X ) ;
try // Para finalmente. try // Para except. ... // Código que puede generar una excepción. except on C : ECustom do begin ... // Manejar ECustom. ... if Predicate ( C . CustomData ) then ... end ; on S : ESomeOtherException do begin // Propagar como otra excepción. raise EYetAnotherException . Create ( S . Message ) ; end ; on E : Exception do begin ... // Manejar otras excepciones. raise ; // Propagar. end ; end ; finally // Código a ejecutar ya sea que se genere o no una excepción (por ejemplo, código de limpieza). end ;
intenta % algún código peligroso catch throw :{ someError , X } -> ok ; % maneja una excepción error : X -> ok ; % maneja otra excepción _:_ -> ok % maneja todas las excepciones después de % limpiar fin
Además del bloque basado en OCaml try...with
, F# también tiene la try...finally
construcción separada, que tiene el mismo comportamiento que un bloque try con una finally
cláusula en otros lenguajes .NET.
A modo de comparación, esta es una traducción del ejemplo de C# anterior.
try try () (* Código que podría lanzar una excepción. *) with | :? System . Net . WebException as ex -> () (* Maneja una WebException. El objeto de excepción se almacena en "ex" . *) | :? exn -> () (* Maneja cualquier excepción CLR. Dado que a la excepción no se le ha dado un identificador, no se puede hacer referencia a ella. *) | _ -> () (* Maneja cualquier cosa que pueda lanzarse, incluidas las excepciones que no sean CLR. *) finally () (* Siempre se ejecuta al salir del bloque try, independientemente de si se lanzaron excepciones o si se manejaron. A menudo se usa para limpiar y cerrar recursos que maneja un archivo de este tipo. Es posible que no se ejecute cuando se llama a Environment.FailFast() y en otras condiciones excepcionales de todo el sistema (por ejemplo, pérdida de energía), o cuando el proceso falla debido a una excepción en otro hilo. *)
A modo de comparación, esta es la traducción del ejemplo de OCaml a continuación.
excepción MyException de cadena * int (* las excepciones pueden llevar un valor *) let _ = try raise ( MyException ( "no hay suficiente comida" , 2 )); printfn "No alcanzado" con | MyException ( s , i ) -> printf "MyException: %s, %d \n " s i | e -> (* captura todas las excepciones *) eprintf "Excepción inesperada : %O" e ; eprintf "%O" e . StackTrace
Haskell no tiene una sintaxis especial para las excepciones. En su lugar, las funciones proporcionan una interfaz try
/ catch
/ finally
/ .etc
importar Preludio ocultando ( catch ) importar Control.Exception instancia Excepción Int instancia Excepción Double main = hacer catch ( catch ( throw ( 42 :: Int )) ( \ e -> print ( 0 , e :: Double ))) ( \ e -> print ( 1 , e :: Int ))
huellas dactilares
(1,42)
En analogía con este C++
#include <iostream> usando el espacio de nombres std ; int main () { try { throw ( int ) 42 ;} catch ( double e ) { cout << "(0," << e << ")" << endl ;} catch ( int e ) { cout << "(1," << e << ")" << endl ;} }
Otro ejemplo es
do { -- Declaraciones en las que se pueden generar errores } ` catch ` \ ex -> do { -- Declaraciones que se ejecutan en caso de una excepción, con 'ex' vinculado a la excepción }
En código puramente funcional, si solo existe una condición de error, el Maybe
tipo puede ser suficiente y es una instancia de Monad
la clase de Haskell por defecto. Se puede lograr una propagación de errores más compleja utilizando las mónadas Error
o ErrorT
, para las que se admite una funcionalidad similar (utilizando ).`catch`
Un try
bloque debe tener al menos una cláusula catch
or finally
y como máximo una finally
cláusula.
try { // Ruta de ejecución normal. throw new EmptyStackException (); } catch ( ExampleExceptionee ) { // Tratar con ExampleException. } finally { // Siempre ejecutar al salir del bloque try (incluyendo cláusulas finally), sin importar si se lanzaron excepciones o si se manejaron. // A menudo se usa para limpiar y cerrar recursos que maneja un archivo de este tipo. // No se puede ejecutar cuando se llama a System.exit() y en otras condiciones excepcionales de todo el sistema (por ejemplo, pérdida de energía). }
El diseño de JavaScript hace que los errores graves o ruidosos sean muy poco frecuentes. Los errores leves o silenciosos son mucho más frecuentes. Los errores graves se propagan a la try
declaración más cercana, que debe ir seguida de una sola catch
cláusula, una sola finally
cláusula o ambas.
try { // Declaraciones en las que se pueden lanzar excepciones throw new Error ( "error" ); } catch ( error ) { // Declaraciones que se ejecutan en caso de una excepción } finally { // Declaraciones que se ejecutan después de cualquier manera }
Si no hay ninguna try
declaración, la página web no se bloquea, sino que se registra un error en la consola y se borra la pila. Sin embargo, JavaScript tiene la peculiaridad interesante de los puntos de entrada invocados externamente de forma asincrónica. Mientras que en la mayoría de los demás lenguajes siempre hay alguna parte del código ejecutándose en todo momento, JavaScript no tiene por qué ejecutarse linealmente de principio a fin. Por ejemplo, el navegador puede invocar detectores de eventos, promesas y temporizadores en un momento posterior y ejecutarlos en un contexto aislado pero compartido con el resto del código. Observe cómo el código siguiente arrojará un nuevo error cada 4 segundos durante un período de tiempo indefinido o hasta que se cierre el navegador, la pestaña o la computadora.
setInterval ( función () { throw new Error ( "Ejemplo de un error arrojado en un intervalo de 4 segundos." ); }, 4000 );
Otra peculiaridad interesante es el polimorfismo: JavaScript puede arrojar valores primitivos como errores.
try { throw 12345 ; // número primitivo } catch ( error ) { console . log ( error ); // registra 12345 como un número primitivo en la consola }
Tenga en cuenta que la catch
cláusula es un cajón de sastre que captura todo tipo de error. No existe ninguna capacidad sintáctica para asignar diferentes controladores a diferentes tipos de error, aparte de las extensiones experimentales y actualmente eliminadas de Gecko de hace muchos años. En cambio, se puede propagar el error mediante una throw
declaración dentro de la catch
declaración o utilizar múltiples casos condicionales. Comparemos un ejemplo en Java y sus equivalentes aproximados en JavaScript.
// Ejemplo en Java try { Integer i = null ; i . intValue (); // lanza una NullPointerException } catch ( NullPointerException error ) { // La variable podría ser nula } catch ( ArithmeticException error ) { // Manejar problemas con números }
// Aproximación n.° 1 en JavaScript try { // Declaraciones en las que se pueden generar excepciones var example = null ; example . toString (); } catch ( error ) { if ( error . type === "TypeError" ) { // La variable puede ser nula } else if ( error . type === "RangeError" ) { // Manejar problemas con números } }
// Aproximación n.° 2 en JavaScript try { try { // Declaraciones en las que se pueden generar excepciones var example = null ; example . toString (); } catch ( error ) { if ( error . type !== "TypeError" ) throw error ; // La variable puede ser nula } } catch ( error ) { if ( error . type !== "RangeError" ) throw error ; // Manejar problemas con números }
Otro aspecto de las excepciones son las promesas, que gestionan la excepción de forma asincrónica. El manejo asincrónico de la excepción tiene la ventaja de que los errores dentro del controlador de errores no se propagan hacia el exterior.
nueva Promesa ( función () { lanzar nuevo Error ( " ¡ Error de ejemplo!" ); }). catch ( función ( err ) { console.log ( "Atrapado " , err ); });
Observe también cómo los controladores de eventos también pueden vincularse con las promesas.
addEventListener ( " unhandledrejection" , función ( evento ) { console.log ( evento.razón ) ; evento.preventDefault (); // evitar registrar el error a través de console.error en la consola--el comportamiento predeterminado }) ; nueva Promesa ( función () { lanzar nuevo Error ( "¡Error de ejemplo!" ); });
Por último, tenga en cuenta que, como JavaScript utiliza la recolección de basura mediante marcado y barrido, nunca hay fugas de memoria de las declaraciones throw porque el navegador limpia automáticamente los objetos muertos, incluso con referencias circulares.
try { // Declaraciones en las que se pueden generar excepciones const obj = {}; obj . selfPropExample = obj ; // referencia circular throw obj ; } catch ( error ) { // Declaraciones que se ejecutan en caso de una excepción }
( ignorar-errores ( / 1 0 )) ( handler-case ( progn ( print "ingresa una expresión" ) ( eval ( read ))) ( error ( e ) ( print e ))) ( unwind-protect ( progn ( print "ingresa una expresión" ) ( eval ( lee ))) ( print "Esta impresión siempre se ejecutará, de manera similar a finalmente." ))
Lua utiliza las funciones pcall
y , tomando una función para que actúe como un bloque.xpcall
xpcall
catch
función foo ( x ) si x entonces devuelve x de lo contrario error "No es un valor verdadero" fin finfunción intento ( arg ) éxito , valor = pcall ( foo , arg ) si no hay éxito entonces imprimir ( "Error: " .. tostring ( valor )) de lo contrario imprimir ( "Devuelto: " .. tostring ( valor )) fin finintento ( "hola" ) -- Devuelto: holaintento ( nil ) - Error: stdin:5: No es un valor verdaderointento ({}) -- Devuelto: tabla: 00809308 si foo ( 42 ) entonces imprime "Éxito" fin -- Éxito
if pcall ( function () -- Hacer algo que podría generar un error. end ) then print "No errors" -- Se ejecuta si la llamada protegida fue exitosa. else print "Error encontrado" -- Se ejecuta si la llamada protegida falló. endimprimir "Hecho" - Siempre se ejecutará
tipo MyError ( Error )
lanzar MyError ( "esto pasó" )
intenta { # algo } catch ( e : MiError ) { guarda e . val = 7 # ... } catch ( e : MiError ) { # ... } catch ( e : Error ) { # ... }
prueba 1 / 0 # evalúa como nulo
"tor" es un operador try-or. En caso de cualquier excepción al evaluar el argumento de la izquierda, se evalúa el argumento de la derecha.
1 / 0 tor 20 # se evalúa como 20
my_result = block my_block { # "block" captura la excepción lanzada por el retorno a continuación # realiza el cálculo si el cálculo_terminado () { my_block . return ( 42 ) # lanza una excepción } }
NSException * excepción = [ NSException excepciónWithName : @"myException" razón : @"yourReason" userInfo : nil ];
@throw excepción ;
@try { ... } @catch ( SomeException * se ) { // Manejar un tipo de excepción específico. ... } @catch ( NSException * ne ) { // Manejar excepciones generales. ... // Propagar la excepción para que se maneje en un nivel superior. @throw ; } @catch ( id ue ) { // Capturar todos los objetos lanzados. ... } @finally { // Realizar la limpieza, ya sea que haya ocurrido una excepción o no. ... }
excepción MyException de cadena * int (* las excepciones pueden llevar un valor *) let _ = try raise ( MyException ( "no hay suficiente comida" , 2 )); print_endline "No alcanzado" con | MyException ( s , i ) -> Printf . printf "MyException: %s, %d \n " s i | e -> (* captura todas las excepciones *) Printf . eprintf "Excepción inesperada: %s" ( Printexc . to_string e ); (*Si se usa Ocaml >= 3.11, también es posible imprimir un backtrace: *) Printexc . print_backtrace stderr ; (* Es necesario habilitar de antemano la grabación del backtrace con Printexc.record_backtrace true o configurando la variable de entorno OCAMLRUNPARAM="b1"*)
El mecanismo de Perldie
para el manejo de excepciones utiliza el método de generar una excepción cuando se envuelve dentro de un bloque. Después de , la variable especial contiene el valor pasado desde .eval { ... };
eval
$@
die
Perl 5.005 agregó la capacidad de lanzar objetos además de cadenas. Esto permite una mejor introspección y manejo de tipos de excepciones.
eval { open ( FILE , $file ) || die MyException::File -> new ( $! ); while ( <FILE> ) { process_line ( $_ ); } close ( FILE ) || die MyException::File -> new ( $! ); }; if ( $@ ) { # El objeto de excepción está en $@ if ( $@ -> isa ( 'MyException::File' )) { # Manejar excepción de archivo } else { # Manejo de excepción genérica # o volver a lanzar con 'die $@' } }
La __DIE__
pseudo-señal se puede atrapar para manejar llamadas a die
. Esto no es adecuado para el manejo de excepciones ya que es global. Sin embargo, se puede utilizar para convertir excepciones basadas en cadenas de paquetes de terceros en objetos.
local $SIG { __DIE__ } = sub { my $err = shift ; if ( $err -> isa ( 'MyException' )) { die $err ; # volver a lanzar } else { # De lo contrario, construye una MyException con $err como una cadena die MyException::Default -> new ( $err ); } };
Las formas que se muestran arriba pueden fallar a veces si la variable global $@
se modifica entre el momento en que se lanza la excepción y el momento en que se verifica en la sentencia. Esto puede ocurrir en entornos multiproceso, o incluso en entornos monoproceso cuando otro código (normalmente llamado en la destrucción de algún objeto) restablece la variable global antes del código de verificación. El siguiente ejemplo muestra una forma de evitar este problema (consulte [1] [ enlace inactivo ] o [2]; cf. [3]). Pero a costa de no poder usar valores de retorno:if ($@)
eval { # Código que podría generar una excepción (usando 'die') pero NO usa la declaración de retorno; 1 ; } o do { # Manejar la excepción aquí. La cadena de excepción está en $@ };
Varios módulos de la Red Integral de Archivos Perl ( CPAN ) amplían el mecanismo básico:
Error
proporciona un conjunto de clases de excepción y permite el uso de la sintaxis try/throw/catch/finally.TryCatch
, y todos permiten el uso de la sintaxis try/catch/finally en lugar de código estándar para manejar las excepciones correctamente.Try::Tiny
Nice::Try
Exception::Class
es una clase base y creadora de clases para clases de excepción derivadas. Proporciona un seguimiento de pila estructurado completo en y .$@->trace
$@->trace->as_string
Fatal
sobrecarga funciones definidas previamente que devuelven verdadero/falso, p. ej. open
, close
, read
, , write
, etc. Esto permite que las funciones integradas y otras se utilicen como si lanzaran excepciones.// El manejo de excepciones solo está disponible en las versiones 5 y superiores de PHP. try { // Código que podría generar una excepción throw new Exception ( 'URL no válida.' ); } catch ( FirstExceptionClass $exception ) { // Código que maneja esta excepción } catch ( SecondExceptionClass $exception ) { // Código que maneja una excepción diferente } finally { // Realizar la limpieza, ya sea que haya ocurrido una excepción o no. }
El manejo de excepciones está disponible en las versiones 8.0 y superiores de PowerBuilder.
INTENTAR // Ruta de ejecución normalCAPTURA (ExampleException ee) // lidiar con la ExampleExceptionFINALMENTE // Esta sección opcional se ejecuta al finalizar cualquiera de los bloques try o catch anterioresFIN DEL INTENTO
trap [Exception] { # Declaraciones que se ejecutan en caso de una excepción } # Declaraciones en las que se pueden lanzar excepciones
Try { Import-Module ActiveDirectory } Catch [Exception1] { # Declaraciones que se ejecutan en caso de una excepción, que coinciden con la excepción } Catch [Exception2],[Exception3etc] { # Declaraciones que se ejecutan en caso de una excepción, que coinciden con cualquiera de las excepciones } Catch { # Declaraciones que se ejecutan en caso de una excepción, que no se manejan de manera más específica }
f = None try : f = open ( "aFileName" , "w" ) f . write ( could_make_error ()) except IOError : print ( "No se puede abrir el archivo" ) except : # captura todas las excepciones print ( "Error inesperado" ) else : # se ejecuta si no se generan excepciones print ( "La escritura del archivo se completó correctamente" ) finally : # acciones de limpieza, siempre se ejecutan si f : f . close ()
tryCatch ({ stop ( "Aquí se señala un error" ) # la clase S3 predeterminada es simpleError, una subclase de error cat ( "Esta y las siguientes líneas no se ejecutan porque el error se capturó antes\n" ) stop ( structure ( simpleError ( "mensaje mySpecialError" ), class = c ( "specialError" , "error" , "condición" )) ) } , specialError = function ( e ){ cat ( "captura errores de la clase specialError\n" ) } , error = function ( e ){ cat ( "captura el error predeterminado\n" ) } , finally = { cat ( "haz algo de limpieza (por ejemplo, setwd)\n" ) } )
REBOL [ Título: "Ejemplos de manejo de excepciones y errores" ]; PRUEBA un bloque; capturando un error! y convirtiendolo en objeto! si hay error? excepcion: try [ 1 / 0 ][ probe disarm exception ]; ATINT da como resultado el valor del bloque o el valor ninguno en caso de error al intentar imprimir [ dividir 1 0 ] ; Las excepciones generadas por el usuario pueden ser de cualquier tipo de datos. Ejemplo: func [ "Una función para generar una excepción" ][ throw "Soy una cadena! excepción" ] catch [ ejemplo ]; Las excepciones generadas por el usuario también pueden tener nombre, ; y las funciones pueden incluir atributos de tiempo de ejecución adicionales sofisticados: func [ "Una función para generar una excepción de error con nombre" [ catch ] ][ throw /name make error! "Soy un error! excepción" 'moniker ] catch /name [ sofisticado ] 'moniker
señal de detención ; hacer a = 1 decir a hacer 100000 /* un retraso */ fin fin detención : decir "El programa fue detenido por el usuario" salir
begin # Haz algo ingenioso raise SomeError , "¡Este es el mensaje de error!" # ¡Vaya! rescue SomeError # Esto se ejecuta cuando se genera una excepción SomeError # rescue AnotherError => error # Aquí, el objeto de excepción se referencia desde la variable # `error' rescue # Esto captura todas las excepciones derivadas de StandardError retry # Esto ejecuta la sección begin nuevamente else # Esto se ejecuta solo si no se generaron excepciones ensure # Esto siempre se ejecuta, con excepción o no end
intentar { % código que podría generar una excepción } Capturar algún error: { % código que maneja esta excepción } Capturar AlgúnOtroError: { % código que maneja esta excepción } Finalmente % bloque opcional { % Este código siempre se ejecutará }
Se pueden crear nuevas excepciones utilizando la new_exception
función, por ejemplo,
new_exception("MyIOError", IOError, "Mi error de E/S");
creará una excepción llamada MyIOError
como una subclase de IOError
. Se pueden generar excepciones utilizando la declaración throw, que puede lanzar objetos S-Lang arbitrarios.
[ "código que podría generar una excepción" ] en: ExceptionClass do: [ : ex | "código que maneja la excepción" ] .
El mecanismo general lo proporciona el mensaje . [6] Las excepciones son simplemente objetos normales que subclases , se lanza una creando una instancia y enviándole un mensaje, p. ej., . El mecanismo de manejo ( ) es nuevamente solo un mensaje normal implementado por . La excepción lanzada se pasa como un parámetro al cierre del bloque de manejo y se puede consultar, así como también enviarle potencialmente , para permitir que continúe el flujo de ejecución.on:do:
Error
#signal
MyException new signal
#on:do:
BlockClosure
#resume
El manejo de excepciones es compatible desde Swift 2.
enum MyException : ErrorType { case Foo ( String , Int ) } func someFunc () throws { throw MyException . Foo ( "no hay suficiente comida" , 2 ) } do { try someFunc () print ( "No se ha alcanzado" ) } catch MyException . Foo ( let s , let i ) { print ( "MyException: \( s ) , \( i ) " ) } catch { print ( "Excepción inesperada : \( error ) " ) }
si { [ catch { foo } err ] } { pone "Error: $err" }
Desde Tcl 8.6, también existe un comando try:
try { someCommandWithExceptions } on ok { res opt } { # manejar casos normales. } trap ListPattern1 { err opt } { # manejar excepciones con un código de error que coincida con ListPattern1 } trap ListPattern2 { err opt } { # ... } on error { err opt } { # manejar todo lo demás. } finally { # ejecutar cualquier comando que deba ejecutarse después del bloque try. }
Con New Try : On Error Resume Next 'do Something (solo se recomienda una declaración) . Catch : On Error GoTo 0 : Select Case . Number Case 0 'esta línea es necesaria cuando se usa la cláusula 'Case Else' debido a la falta de la palabra clave "Is" en VBScript. Declaración de caso 'sin excepción Case SOME_ERRORNUMBER 'manejo de excepciones Case Else 'excepción desconocida End Select : End With ' *** Probar clase *** Probar clase mstrDescription privado mlngHelpContext privado mstrHelpFile privado mlngNumber privado mstrSource privado Public Sub Catch () mstrDescription = Err . Descripción mlngHelpContext = Err . HelpContext mstrHelpFile = Err . HelpFile mlngNumber = Err . Número mstrSource = Err . Fuente End Sub Propiedad pública Obtener fuente () Fuente = mstrSource Fin de la propiedad Propiedad pública Obtener número () Número = mlngNumber Fin de la propiedad Propiedad pública Obtener HelpFile () HelpFile = mstrHelpFile Fin de la propiedad Propiedad pública Obtener HelpContext () HelpContext = mlngHelpContext Fin de la propiedad Propiedad pública Obtener Description () Description = mstrDescription Fin de la propiedad Fin de la clase
[7]
La sintaxis de manejo de excepciones es muy similar a la de Basic. El manejo de errores es local en cada procedimiento.
On Error GoTo HandlerLabel 'Cuando se ha producido un error, salta a HandlerLabel, que está definido en cualquier parte dentro de Function o Sub 'o On Error GoTo 0 'desactiva el control de errores. Error provoca un error de ejecución fatal y detiene la aplicación 'o On Error Resume Next 'El objeto Err está configurado, pero la ejecución continúa en el siguiente comando. Aún puede usar el objeto Err para comprobar el estado del error. '... Err . Raise 6 'Genera un error de "desbordamiento" utilizando el objeto integrado Err. Si no hay un controlador de errores, el procedimiento de llamada puede capturar la excepción con la misma sintaxis '... FinallyLabel : 'solo etiqueta común dentro del procedimiento (emulación no oficial de la sección Finally de otros lenguajes) ' código de limpieza, siempre ejecutado Exit Sub ' sale del procedimiento 'porque buscamos la declaración Exit Sub, el siguiente código está oculto para la ejecución sin errores HandlerLabel : 'define una etiqueta común, que se utiliza aquí para el manejo de excepciones. Si Err . Number = 6 Entonces 'la declaración Select Case es normalmente una mejor solución Resume FinallyLabel 'continúa la ejecución en una etiqueta específica. Normalmente, algo con el significado de "Finalmente" en otros idiomas 'o Resume Next 'continúa la ejecución en la declaración junto a "Err.Raise 6" 'o Resume 'continúa la ejecución en (repetir) la declaración "Err.Raise 6" End If MsgBox Err . Número & " " & Err . Origen & " " & Erl & " " & Err . Descripción & " " & Err . LastDllError 'mostrar cuadro de mensaje con propiedades de error importantes ' Erl es una variable global de número de línea incorporada de VB6 (si se usa). Normalmente se usa algún tipo de complemento de IDE, que etiqueta cada línea de código con un número antes de la compilación Resume FinallyLabel
Ejemplo de implementación específica (no oficial) de manejo de excepciones, que utiliza un objeto de la clase "Try".
Con New Try : On Error Resume Next 'Crear un nuevo objeto de la clase "Try" y usarlo. Luego, establecer este objeto como predeterminado. Puede ser "Dim T As New Try: ... ... T.Catch 'hacer algo (solo se recomienda una declaración) . Catch : On Error GoTo 0 : Select Case . Number 'Llamar al procedimiento Try.Catch(). Luego, desactivar el manejo de errores. Luego, usar una declaración "similar a un interruptor" en el resultado de la propiedad Try.Number (valor de la propiedad Err.Number del objeto Err integrado) Case SOME_ERRORNUMBER 'manejo de excepciones Case Is <> 0 'Cuando Err.Number es cero, no se ha producido ningún error 'excepción desconocida End Select : End With ' *** Probar clase *** mstrDescription privado como cadena mlngHelpContext privado como largo mstrHelpFile privado como cadena mlngLastDllError privado como largo mlngNumber privado como largo mstrSource privado como cadena Public Sub Catch () mstrDescription = Err . Descripción mlngHelpContext = Err . HelpContext mstrHelpFile = Err . HelpFile mlngLastDllError = Err . LastDllError mlngNumber = Err . Número mstrSource = Err . Fuente End Sub Propiedad pública Obtener fuente () como cadena Fuente = mstrSource Fin de la propiedad Propiedad pública Obtener número () Como número largo = mlngNumber Fin de propiedad Propiedad pública Obtener LastDllError () Como Long LastDllError = mlngLastDllError Fin de la propiedad Propiedad pública Obtener HelpFile () como cadena HelpFile = mstrHelpFile Fin de la propiedad Propiedad pública Obtener HelpContext () Mientras HelpContext = mlngHelpContext Fin de la propiedad Propiedad pública Obtener descripción () como cadena Descripción = mstrDescription Fin de la propiedad
[7]
Un Try
bloque debe tener al menos una cláusula Catch
o Finally
cláusula y como máximo una Finally
cláusula.
Try ' código a ejecutar aquí Catch ex As Exception When condition ' Manejar excepción cuando una condición específica es verdadera. El objeto de excepción se almacena en "ex". Catch ex As ExceptionType ' Manejar excepción de un tipo especificado (es decir, DivideByZeroException, OverflowException, etc.) Catch ex As Exception ' Manejar excepción (capturar todas las excepciones de un tipo no especificado previamente) Catch ' Maneja cualquier cosa que pueda lanzarse, incluidas las excepciones que no sean de CLR. Finally ' Siempre se ejecuta al salir del bloque try (incluidas las cláusulas catch), independientemente de si se lanzaron excepciones o si se manejaron. ' A menudo se usa para limpiar y cerrar recursos que maneja un archivo. ' No se puede ejecutar cuando se llama a Environment.FailFast() y en otras condiciones excepcionales de todo el sistema (por ejemplo, pérdida de energía), o cuando el proceso falla debido a una excepción en otro hilo. End Try
try % Bloquear para proteger catch TraceId do % Código a ejecutar en caso de una excepción; TraceId da acceso a la información de la excepción finally % El código se ejecutará independientemente de cómo se comporten las otras partes end try
[8]
public static void Main ( Args _args ) { try { // Código que podría generar una excepción. } catch ( Excepción :: Error ) // O cualquier otro tipo de excepción. { // Procesar el error. } catch { // Procesar cualquier otro tipo de excepción no manejado previamente. } // El código aquí se ejecutará siempre que se detecte alguna excepción. }
retry