Compartir a través de


Escribir un filtro de excepción

Para controlar una excepción puede saltar al nivel del controlador de la excepción o puede continuar la ejecución. En lugar de usar el código de controlador de excepciones para controlar la excepción y pasar por ella, puede usar una expresión filter para corregir el problema. Después, con el valor devuelto EXCEPTION_CONTINUE_EXECUTION (-1), puede reanudar el flujo normal sin borrar la pila.

Nota:

Algunas excepciones impiden que continúe el flujo. Si filter se evalúa como -1 para una de estas excepciones, el sistema genera una nueva excepción. Si llama a RaiseException, puede determinar si la excepción continuará.

Por ejemplo, el código siguiente usa una llamada a una función en la expresión filter. Esta función controla el problema y devuelve -1 para reanudar el flujo de control normal:

// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int Eval_Exception(int);
int main() {
    __try {
        ;
    }
    __except (Eval_Exception(GetExceptionCode())) {
        ;
    }
}
void HandleOverflow() {
    // Gracefully recover
}
int Eval_Exception(int n_except) {
    if (
        n_except != STATUS_INTEGER_OVERFLOW &&
        n_except != STATUS_FLOAT_OVERFLOW
    ) {
        // Pass on most exceptions
        return EXCEPTION_CONTINUE_SEARCH;
    }
    // Execute some code to clean up problem
    HandleOverflow();
    return EXCEPTION_CONTINUE_EXECUTION;
}

Es conveniente usar una llamada a una función en la expresión filter siempre que filter necesite realizar alguna tarea compleja. La evaluación de la expresión hace que se ejecute la función (en este caso, Eval_Exception).

Observe el uso de GetExceptionCode para determinar la excepción. Se debe llamar a esta función dentro de la expresión de filtro de la instrucción __except. Eval_Exception no puede llamar a GetExceptionCode, pero se le debe pasar el código de la excepción.

Este controlador pasa el control a otro controlador a menos que la excepción sea un desbordamiento de números enteros o de punto flotante. Si es así, el controlador llama a una función (HandleOverflow es solo un ejemplo, no una función de API) para intentar recuperarse correctamente de la excepción. El bloque de instrucciones __except, que en este ejemplo está vacío, no se puede ejecutar nunca porque Eval_Exception nunca devuelve EXCEPTION_EXECUTE_HANDLER (1).

El uso de una llamada a una función es una buena técnica de uso general para trabajar con expresiones de filtro complejas. Otras dos características útiles del lenguaje C son:

  • El operador condicional

  • El operador de coma

El operador condicional suele ser útil aquí. Puede usarse para comprobar un código de retorno concreto y, después, devolver uno de dos valores diferentes. Por ejemplo, el filtro del código siguiente reconoce la excepción solo si esta es STATUS_INTEGER_OVERFLOW:

__except (GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0)

El propósito del operador condicional en este caso es principalmente proporcionar claridad, ya que el código siguiente genera los mismos resultados:

__except (GetExceptionCode() == STATUS_INTEGER_OVERFLOW)

El operador condicional es más útil en situaciones en las que le interese que el filtro se evalúe como -1, EXCEPTION_CONTINUE_EXECUTION.

El operador de coma permite ejecutar varias expresiones en secuencia. Después, devuelve el valor de la última expresión. Por ejemplo, el código siguiente almacena el código de excepción en una variable y después lo comprueba:

__except (nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW)

Consulte también

Escribir un controlador de excepciones
Structured Exception Handling (C/C++)