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 __try
jest 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:
Sekcja chroniona jest wykonywana.
Jeśli podczas wykonywania sekcji chronionej nie wystąpi wyjątek, program kontynuuje wykonywanie instrukcji po klauzuli
__except
.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ącychtry-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
__except
i __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
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla