Instrucción try-except
La instrucción try-except
es una extensión específica de Microsoft que admite el manejo estructurado de excepciones en los lenguajes C y C++.
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
Gramática
try-except-statement
:
__try
compound-statement
__except (
expression
)
compound-statement
Comentarios
La instrucción try-except
es una extensión de Microsoft para los lenguajes C y C++. Permite que las aplicaciones de destino obtengan control cuando se producen eventos que normalmente finalizan la ejecución del programa. Estos eventos se denominan excepciones estructuradas, o bien excepciones para abreviar. El mecanismo que trata estas excepciones se denomina control estructurado de excepciones (SEH).
Para obtener información al respecto, vea la instrucción try-finally.
Las excepciones pueden estar basadas en hardware o software. El control estructurado de excepciones es útil incluso cuando las aplicaciones no se pueden recuperar completamente de las excepciones de hardware o software. SEH permite mostrar información de error y capturar el estado interno de la aplicación para ayudar a diagnosticar el problema. Es especialmente útil para problemas intermitentes que no son fáciles de reproducir.
Nota:
El control de excepciones estructurado funciona con Win32 para archivos de código fuente de C y C++. Sin embargo, no está diseñado específicamente para C++. Para asegurarse de que el código será más portable, use el control de excepciones de C++. Además, el control de excepciones de C++ es más flexible, ya que puede controlar excepciones de cualquier tipo. Para los programas de C++, le recomendamos que utilice el manejo de excepciones nativo de C++: instrucciones try, catch y throw.
La instrucción compuesta detrás de la cláusula __try
es el cuerpo o la sección protegida. La expresión __except
también se conoce como la expresión de filtro. Su valor determina cómo se controla la excepción. La instrucción compuesta detrás de la cláusula __except
es el controlador de excepción. El controlador especifica las acciones que se deben realizar si se produce una excepción durante la ejecución de la sección body. La ejecución continúa de la siguiente manera:
Se ejecuta la sección protegida.
Si no se produce ninguna excepción durante la ejecución de la sección protegida, continúa la ejecución de la instrucción después de la cláusula
__except
.Si se produce una excepción durante la ejecución de la sección protegida, o en cualquier rutina que llame la sección protegida, se evalúa la expresión
__except
. Hay tres valores posibles:EXCEPTION_CONTINUE_EXECUTION
(-1) Se descarta la excepción. La ejecución continúa en el punto donde se ha producido la excepción.EXCEPTION_CONTINUE_SEARCH
(0) No se reconoce la excepción. La búsqueda de un controlador continúa hacia la parte superior de la pila, primero con las instruccionestry-except
contenedoras y, después, con los controladores siguientes que tengan mayor prioridad.EXCEPTION_EXECUTE_HANDLER
(1) La excepción se reconoce. Se transfiere el control al controlador de excepciones mediante la ejecución de la instrucción compuesta__except
; después, la ejecución continúa tras el bloque__except
.
La expresión __except
se evalúa como una expresión de C. Está limitado a un solo valor, el operador de expresión condicional o el operador de coma. Si se requiere un mayor procesamiento, la expresión puede llamar a una rutina que devuelva uno de los tres valores enumerados anteriormente.
Cada aplicación puede tener su propio controlador de excepciones.
No es válido saltar dentro de una instrucción __try
, pero sí fuera. El controlador de excepciones no se llama si un proceso finaliza en medio de la ejecución de una instrucción try-except
.
Por compatibilidad con versiones anteriores, _try, _except y _leave son sinónimos de __try
, __except
y __leave
a menos que se especifique la opción del compilador /Za (Deshabilitar extensiones de lenguaje).
La palabra clave __leave
.
La palabra clave __leave
solo es válida dentro de la sección protegida de una instrucción try-except
y su efecto es saltar al final de la sección protegida. La ejecución de la primera instrucción continúa después del controlador de excepciones.
Una instrucción goto
también puede saltar fuera de la sección protegida y no degrada el rendimiento como lo hace en una instrucción try-finally. Esto se debe a que no se produce el desenredo de la pila. Sin embargo, se recomienda usar la palabra clave __leave
en lugar de una instrucción goto
. El motivo es que es menos probable que comete un error de programación si la sección de protección es grande o compleja.
Funciones intrínsecas de control de excepciones estructurado
El manejo estructurado de excepciones proporciona dos funciones intrínsecas que están disponibles para usar con la instrucción try-except
: GetExceptionCode y GetExceptionInformation.
GetExceptionCode
devuelve el código (un entero de 32 bits) de la excepción.
La función intrínseca GetExceptionInformation
devuelve un puntero a una estructura EXCEPTION_POINTERS que contiene información adicional sobre la excepción. A través de este puntero, se puede tener acceso al estado que tenía el equipo en el momento de producirse una excepción de hardware. La estructura es como sigue:
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
Los tipos de puntero PEXCEPTION_RECORD
y PCONTEXT
se definen en el archivo de inclusión <winnt.h>, y _EXCEPTION_RECORD
y _CONTEXT
se definen en el archivo de inclusión <excpt.h>
Puede usar GetExceptionCode
en el controlador de excepciones. Sin embargo, solo puede usar GetExceptionInformation
dentro de la expresión de filtro de excepciones. La información a la que apunta suele estar en la pila y ya no está disponible cuando el control se transfiere al controlador de excepciones.
La función intrínseca AbnormalTermination está disponible dentro de un controlador de terminación. Devuelve 0 si el cuerpo de la instrucción try-finally finaliza secuencialmente. En todos los demás casos, devuelve 1.
<excpt.h> define algunos nombres alternativos para estos intrínsecos:
GetExceptionCode
es equivalente a _exception_code
GetExceptionInformation
es equivalente a _exception_info
AbnormalTermination
es equivalente a _abnormal_termination
Ejemplo
// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
puts("in filter.");
if (code == EXCEPTION_ACCESS_VIOLATION)
{
puts("caught AV as expected.");
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
puts("didn't catch AV, unexpected.");
return EXCEPTION_CONTINUE_SEARCH;
};
}
int main()
{
int* p = 0x00000000; // pointer to NULL
puts("hello");
__try
{
puts("in try");
__try
{
puts("in try");
*p = 13; // causes an access violation exception;
}
__finally
{
puts("in finally. termination: ");
puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
}
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
puts("in except");
}
puts("world");
}
Output
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world
Consulte también
Escribir un controlador de excepciones
Structured Exception Handling (C/C++)
Palabras clave