Obsługa wyjątków strukturalnych (C/C++)
Obsługa wyjątków strukturalnych (SEH) to rozszerzenie firmy Microsoft do języków C i C++ do obsługi niektórych wyjątkowych sytuacji kodu, takich jak błędy sprzętowe, bezpiecznie. Mimo że systemy Windows i Microsoft C++ obsługują standard SEH, zalecamy używanie standardowej obsługi wyjątków C++ w standardzie ISO w kodzie C++. Dzięki temu kod jest bardziej przenośny i elastyczny. Jednak aby zachować istniejący kod lub określonego rodzaju programów, nadal może być konieczne użycie SEH.
Specyficzne dla firmy Microsoft:
Gramatyka
try-except-statement
:
__try
compound-statement
__except
(
filter-expression
)
compound-statement
try-finally-statement
:
__try
compound-statement
__finally
compound-statement
Uwagi
Za pomocą protokołu SEH można upewnić się, że zasoby, takie jak bloki pamięci i pliki, są prawidłowo zwalniane, jeśli wykonanie nieoczekiwanie zakończy się. Można również obsłużyć konkretne problemy — na przykład za mało pamięci — za pomocą zwięzłego kodu ustrukturyzowanego, który nie opiera się na goto
instrukcjach ani skomplikowanych testach kodów powrotnych.
Instrukcje try-except
i try-finally
, o których mowa w tym artykule, to rozszerzenia firmy Microsoft dla języków C i C++. Obsługują SEH, umożliwiając aplikacjom kontrolę nad programem po zdarzeniach, które w przeciwnym razie zakończą wykonywanie. Mimo że SEH współpracuje z plikami źródłowymi języka C++, nie jest specjalnie zaprojektowany dla języka C++. Jeśli używasz SEH w programie C++, który kompilujesz przy użyciu /EHa
opcji lub /EHsc
, destruktory dla obiektów lokalnych są wywoływane, ale inne zachowanie wykonywania może nie być oczekiwane. Aby zapoznać się z ilustracją, zobacz przykład w dalszej części tego artykułu. W większości przypadków zamiast SEH zalecamy użycie obsługi wyjątków standardu ISO C++. Korzystając z obsługi wyjątków w języku C++, możesz upewnić się, że kod jest bardziej przenośny i można obsługiwać wyjątki dowolnego typu.
Jeśli masz kod C, który używa protokołu SEH, możesz go mieszać z kodem C++, który korzysta z obsługi wyjątków języka C++. Aby uzyskać informacje, zobacz Obsługa wyjątków strukturalnych w języku C++.
Istnieją dwa mechanizmy SEH:
Procedury obsługi wyjątków lub
__except
bloki, które mogą odpowiadać na lub odrzucać wyjątek nafilter-expression
podstawie wartości. Aby uzyskać więcej informacji, zobacztry-except
instrukcję.Procedury obsługi zakończenia lub
__finally
bloki, które są zawsze wywoływane, niezależnie od tego, czy wyjątek powoduje zakończenie, czy nie. Aby uzyskać więcej informacji, zobacztry-finally
instrukcję.
Te dwa rodzaje procedur obsługi są odrębne, ale są ściśle powiązane przez proces znany jako odwijanie stosu. W przypadku wystąpienia wyjątku strukturalnego system Windows wyszukuje ostatnio zainstalowaną procedurę obsługi wyjątków, która jest obecnie aktywna. Procedura obsługi może wykonać jedną z trzech czynności:
Nie można rozpoznać wyjątku i przekazać kontrolę do innych procedur obsługi (
EXCEPTION_CONTINUE_SEARCH
).Rozpoznaj wyjątek, ale go odrzuć (
EXCEPTION_CONTINUE_EXECUTION
).Rozpoznaj wyjątek i obsłuż go (
EXCEPTION_EXECUTE_HANDLER
).
Procedura obsługi wyjątków, która rozpoznaje wyjątek, może nie znajdować się w funkcji, która była uruchomiona po wystąpieniu wyjątku. Może to być w funkcji znacznie wyższej na stosie. Obecnie uruchomiona funkcja i wszystkie inne funkcje w ramce stosu są przerywane. W trakcie tego procesu stos jest unwound. Oznacza to, że lokalne zmienne niestatyczne zakończonych funkcji są czyszczone ze stosu.
W miarę odwijania stosu system operacyjny wywołuje wszystkie programy obsługi zakończenia napisane dla każdej funkcji. Korzystając z procedury obsługi zakończenia, należy wyczyścić zasoby, które w przeciwnym razie pozostaną otwarte z powodu nietypowego zakończenia. Jeśli wprowadzono sekcję krytyczną, możesz zamknąć ją w procedurze obsługi kończenia. Gdy program zostanie zamknięty, możesz wykonać inne zadania sprzątania, takie jak zamykanie i usuwanie plików tymczasowych.
Następne kroki
Przykład
Jak wspomniano wcześniej, destruktory dla obiektów lokalnych są wywoływane, jeśli używasz SEH w programie języka C++ i skompiluj je przy użyciu /EHa
opcji lub /EHsc
. Jednak zachowanie podczas wykonywania może nie być oczekiwane, jeśli używasz również wyjątków języka C++. W tym przykładzie pokazano te różnice behawioralne.
#include <stdio.h>
#include <Windows.h>
#include <exception>
class TestClass
{
public:
~TestClass()
{
printf("Destroying TestClass!\n");
}
};
__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
printf("Throwing C++ exception\n");
throw std::exception("");
#else
printf("Triggering SEH exception\n");
volatile int *pInt = 0x00000000;
*pInt = 20;
#endif
}
__declspec(noinline) void TestExceptions()
{
TestClass d;
TestCPPEX();
}
int main()
{
__try
{
TestExceptions();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("Executing SEH __except block\n");
}
return 0;
}
Jeśli używasz /EHsc
polecenia do skompilowania tego kodu, ale lokalne makro CPPEX
kontroli testów jest niezdefiniowane, TestClass
destruktor nie zostanie uruchomiony. Dane wyjściowe wyglądają następująco:
Triggering SEH exception
Executing SEH __except block
Jeśli używasz /EHsc
polecenia do kompilowania kodu i CPPEX
jest definiowany za pomocą polecenia /DCPPEX
(tak, aby zgłaszany był wyjątek języka C++), TestClass
destruktor jest uruchamiany, a dane wyjściowe wyglądają następująco:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
Jeśli używasz /EHa
polecenia do skompilowania kodu, destruktor wykonuje, TestClass
czy wyjątek został zgłoszony przy użyciu standardowego wyrażenia C++ throw
, czy też przy użyciu SEH. Oznacza to, czy CPPEX
jest definiowany, czy nie. Dane wyjściowe wyglądają następująco:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
Aby uzyskać więcej informacji, zobacz /EH
(Model obsługi wyjątków).
KONIEC specyficzny dla firmy Microsoft
Zobacz też
Obsługa wyjątków
Słowa kluczowe
<exception>
Błędy i obsługa wyjątków
Obsługa wyjątków strukturalnych (Windows)
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