Udostępnij za pośrednictwem


Pisanie filtra wyjątku

Możesz obsłużyć wyjątek wykonując skok na poziom programu obsługi wyjątków lub kontynuując wykonywanie.Zamiast używania kodu programu obsługi wyjątku, aby obsłużyć wyjątek i przejść przez kod, możesz użyć filtru, aby oczyścić problem, a następnie, zwracając ‑1, wznowić normalny przepływ bez czyszczenia stosu.

[!UWAGA]

Niektóre wyjątki nie mogą być kontynuowane.Jeśli filtr zostanie dla takiego wyjątku obliczony na ‑1, to system zgłosi nowy wyjątek.Jeśli wywołasz RaiseException, możesz określić czy kontynuować wyjątek.

Na przykład, następujący kod używa wywołania funkcji w wyrażeniu filtru: funkcja ta obsługuje problem, a następnie zwraca wartość ‑1, aby wznowić normalny przepływ sterowania.

// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
   int Eval_Exception( int );

   __try {}

   __except ( Eval_Exception( GetExceptionCode( ))) {
      ;
   }

}
void ResetVars( int ) {}
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
   ResetVars( 0 );   // initializes data to 0
   return EXCEPTION_CONTINUE_EXECUTION;
}

Dobrym pomysłem jest używać wywołania funkcji w wyrażeniu filtru, jeśli filtr musi wykonać jakiekolwiek złożone działania.Obliczanie wyrażenia powoduje wykonanie funkcji, w tym przypadku jest to Eval_Exception.

Zwróć uwagę na użycie GetExceptionCode do określenia wyjątku.Musisz wywołać tę funkcję wewnątrz samego filtru.Eval_Exception nie może wywołać GetExceptionCode, ale musi mieć przekazany kod wyjątku.

Ten program obsługi wyjątków przekazuje sterowanie do innego programu obsługi wyjątków, dopóki wyjątek nie dotyczy przepełnienia liczby całkowitej lub zmiennoprzecinkowej.Jeśli tak się stanie, program obsługi wyjątku wywołuje funkcję (ResetVars jest tylko przykładem, a nie funkcją API), aby zresetować niektóre zmienne globalne.Statement-block-2, który jest w tym przykładzie pusty, może nigdy nie być wykonany, ponieważ Eval_Exception nigdy nie zwraca EXCEPTION_EXECUTE_HANDLER (1).

Używanie wywołań funkcji jest dobrą techniką ogólnego przeznaczenia do radzenia sobie ze złożonymi wyrażeniami filtrującymi.Dwie inne funkcje języka C, które są przydatne to:

  • Operator warunkowy

  • Operator przecinka

Operator warunkowy jest często przydatny, ponieważ może być użyty do wyszukiwania określonego kodu zwracanej wartości, a następnie zwrócić jedną z dwóch, różnych wartości.Na przykład, filtr w poniższym kodzie rozpoznaje wyjątek, tylko jeśli wyjątkiem jest STATUS_INTEGER_OVERFLOW:

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

Celem operatora warunkowego w tym przypadku jest głównie zapewnienie czytelności, ponieważ następujący kod generuje te same wyniki:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {

Operator warunkowy jest bardziej użyteczny w sytuacjach, w których możesz chcieć, aby filtr został obliczony na wartość ‑1 (EXCEPTION_CONTINUE_EXECUTION).

Operator przecinka umożliwia wykonanie wielu, niezależnych operacji wewnątrz pojedynczego wyrażenia.Efektem jest (w przybliżeniu) wykonanie wielu instrukcji, a następnie zwrócenie wartości ostatniego wyrażenia.Na przykład, poniższy kod przechowuje kod wyjątku w zmiennej, a następnie ją sprawdza:

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

Zobacz też

Informacje

Pisanie programu do obsługi wyjątku

Obsługa wyjątków strukturalnych (C/C++)