try-except Instrukcja

Instrukcja try-except jest rozszerzeniem specyficznym dla firmy Microsoft, które obsługuje obsługę wyjątków strukturalnych w językach C i C++.

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

Gramatyka

try-except-statement:
__try compound-statement __except ( expression ) compound-statement

Uwagi

Instrukcja try-except to rozszerzenie firmy Microsoft do języków C i C++. Dzięki temu aplikacje docelowe mogą kontrolować, kiedy wystąpią zdarzenia, które zwykle kończą wykonywanie programu. Takie zdarzenia są nazywane wyjątkami ustrukturyzowanymi lub wyjątkami dla krótkich. Mechanizm, który dotyczy tych wyjątków, jest nazywany obsługą wyjątków strukturalnych (SEH).

Aby uzyskać powiązane informacje, zobacz instrukcję try-finally.

Wyjątki mogą być oparte na sprzęcie lub oprogramowaniu. Obsługa wyjątków strukturalnych jest przydatna nawet wtedy, gdy aplikacje nie mogą całkowicie odzyskać sprawności po wyjątkach sprzętu lub oprogramowania. SEH umożliwia wyświetlanie informacji o błędach i pułapkę wewnętrznego stanu aplikacji w celu ułatwienia zdiagnozowania problemu. Jest to szczególnie przydatne w przypadku sporadycznych problemów, które nie są łatwe do odtworzenia.

Uwaga

Strukturalna obsługa wyjątków działa z Win32 dla plików źródłowych C i C++. Nie jest to jednak specjalnie zaprojektowane dla języka C++. Można zapewnić, że kod będzie bardziej przenośny przy użyciu obsługi wyjątków C++. Ponadto, obsługa wyjątków C++ jest bardziej elastyczna, gdyż może obsługiwać wyjątki dowolnego typu. W przypadku programów języka C++ zalecamy używanie natywnej obsługi wyjątków w języku C++: try, catch i throw instrukcji.

Instrukcja złożone po klauzuli __tryjest treść lub sekcja chroniona . Wyrażenie __except jest również nazywane wyrażeniem filtru. Jego wartość określa sposób obsługi wyjątku. Złożone wyrażenie po klauzuli __except to program obsługi wyjątków. Procedura obsługi określa akcje, które należy wykonać, jeśli podczas wykonywania sekcji treści jest zgłaszany wyjątek. Wykonanie jest kontynuowane w następujący sposób:

  1. Sekcja chroniona jest wykonywana.

  2. Jeśli podczas wykonywania sekcji chronionej nie wystąpi wyjątek, program kontynuuje wykonywanie instrukcji po klauzuli __except.

  3. Jeśli wyjątek występuje podczas wykonywania chronionej sekcji lub w dowolnej procedurze wywołania sekcji chronionej, __except wyrażenie jest oceniane. Istnieją trzy możliwe wartości:

    • EXCEPTION_CONTINUE_EXECUTION (-1) Wyjątek jest odrzucany. Kontynuuj wykonywanie w punkcie, w którym wystąpił wyjątek.

    • EXCEPTION_CONTINUE_SEARCH (0) Wyjątek nie jest rozpoznawany. Kontynuuj wyszukiwanie stosu dla procedury obsługi, najpierw w przypadku instrukcji zawierających try-except instrukcje, a następnie dla procedur obsługi z następnym najwyższym priorytetem.

    • EXCEPTION_EXECUTE_HANDLER (1) Rozpoznano wyjątek. Przenieś kontrolkę do procedury obsługi wyjątków, wykonując instrukcję złożoną __except , a następnie kontynuuj wykonywanie po __except bloku.

Wyrażenie __except jest oceniane jako wyrażenie języka C. Jest ograniczona do pojedynczej wartości, operatora wyrażenia warunkowego lub operatora przecinka. Jeśli wymagane jest bardziej rozległe przetwarzanie, wyrażenie może wywołać procedurę, która zwraca jedną z trzech wartości wymienionych powyżej.

Każda aplikacja może mieć własną obsługę wyjątków.

Nie jest ważne, aby wskoczyć do __try instrukcji, ale ważne, aby wyskoczyć z jednego. Procedura obsługi wyjątków nie jest wywoływana, jeśli proces zostanie zakończony w trakcie wykonywania try-except instrukcji.

Aby uzyskać zgodność z poprzednimi wersjami, _try, _except i _leave są synonimami , __try__excepti __leave chyba że określono opcję kompilatora /Za (Wyłącz rozszerzenia języka).

Słowo __leave kluczowe

Słowo __leave kluczowe jest prawidłowe tylko w chronionej sekcji try-except instrukcji, a jej efektem jest przejście na koniec chronionej sekcji. Wykonywanie jest kontynuowane po pierwszej instrukcji następującej po programie obsługi wyjątków.

Instrukcja goto może również wyskoczyć z chronionej sekcji i nie obniża wydajności, tak jak w instrukcji try-finally . Dzieje się tak, ponieważ odwijanie stosu nie występuje. Zalecamy jednak użycie słowa kluczowego __leave zamiast instrukcji goto . Przyczyną jest to, że mniej prawdopodobne jest popełnienie błędu programistycznego, jeśli chroniona sekcja jest duża lub złożona.

Funkcje wewnętrzne obsługi wyjątków strukturalnych

Obsługa wyjątków strukturalnych zapewnia dwie funkcje wewnętrzne, które są dostępne do użycia z instrukcją try-except : GetExceptionCode i GetExceptionInformation.

GetExceptionCode Zwraca kod (32-bitową liczbę całkowitą) wyjątku.

Funkcja GetExceptionInformation wewnętrzna zwraca wskaźnik do struktury EXCEPTION_POINTERS zawierającej dodatkowe informacje o wyjątku. Za pomocą tego wskaźnika można uzyskać dostęp do stanu maszyny w momencie wystąpienia wyjątku sprzętowego. Struktura jest następująca:

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

Typy PEXCEPTION_RECORD wskaźników i PCONTEXT są zdefiniowane w pliku <dołączania winnt.h> i _CONTEXT_EXCEPTION_RECORD są zdefiniowane w pliku include <excpt.h>

Można użyć GetExceptionCode w programie obsługi wyjątków. Można jednak używać GetExceptionInformation tylko w wyrażeniu filtru wyjątku. Informacje, do których wskazuje, są zazwyczaj na stosie i nie są już dostępne po przeniesieniu kontroli do programu obsługi wyjątków.

Funkcja wewnętrzna AbnormalTermination jest dostępna w programie obsługi zakończenia. Zwraca wartość 0, jeśli treść instrukcji try-finally kończy się sekwencyjnie. We wszystkich pozostałych przypadkach zwraca wartość 1.

<excpt.h> definiuje kilka alternatywnych nazw dla tych wewnętrznych:

GetExceptionCode jest odpowiednikiem _exception_code

GetExceptionInformation jest odpowiednikiem _exception_info

AbnormalTermination jest odpowiednikiem _abnormal_termination

Przykład

// 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");
}

Wynik

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

Zobacz też

Pisanie procedury obsługi wyjątków
Obsługa wyjątków strukturalnych (C/C++)
Słowa kluczowe