Loading AI tools
Z Wikipedii, wolnej encyklopedii
Wyjątek (ang. exception) - mechanizm przepływu sterowania używany w procesorach oraz współczesnych językach programowania do obsługi zdarzeń wyjątkowych, a w szczególności błędów, których wystąpienie zmienia prawidłowy przebieg wykonywania programu.
W momencie zajścia niespodziewanego zdarzenia generowany jest wyjątek, który musi zostać obsłużony poprzez zapamiętanie bieżącego stanu programu i przejście do procedury jego obsługi.
W niektórych sytuacjach po obsłużeniu wyjątku można powrócić do wykonywania przerwanego kodu, korzystając z zapamiętanych informacji stanu. Przykładowo obsługa błędu braku strony pamięci polega najczęściej na pobraniu brakującej strony z pliku wymiany, co umożliwia kontynuowanie pracy programu, natomiast błąd dzielenia przez zero powoduje, że wykonywanie dalszych obliczeń nie ma sensu i musi zostać definitywnie przerwane.
Wyjątki w procesorach są zdarzeniami, których wynikiem jest przerwanie wykonania bieżącego strumienia instrukcji i przekazanie sterowania do oprogramowania systemowego w celu programowej reakcji na zdarzenie.
Wyjątki dzielą się na synchroniczne, obsługiwane bezpośrednio po wystąpieniu, oraz asynchroniczne, których obsługa może, w zależności od bieżącego priorytetu procesora, zostać opóźniona.
Do wyjątków asynchronicznych należą przerwania. Wyjątki synchroniczne - to pułapki (traps) i błędy (faults, aborts, errors).
Przerwania mogą być generowane sprzętowo przez sterowniki urządzeń zewnętrznych oraz - w nowocześniejszych architekturach (np. ARM) - programowo przez procesor.
Pułapki są generowane przez jednostkę wykonawczą procesora w wyniku wykonania instrukcji, na końcu jej wykonania. Pułapki służą do trzech celów:
Przy wystąpieniu pułapki wykonanie instrukcji, która ją spowodowała, zostaje normalnie zakończone.
Błędy mogą być generowane przez procesor lub jego otoczenie. Charakterystyczną cechą błędów jest to, że uniemożliwiają one zakończenie wykonania instrukcji, podczas której wystąpiły. Są to np:
W językach programowania wsparcie dla wyjątków realizowane jest na poziomie składni i semantyki danego języka. Zgłoszenie sytuacji wyjątkowej możliwe jest w dowolnym miejscu kodu poprzez instrukcje zwane raise lub throw. Od ich angielskich nazw w języku polskim proces ten nazywany jest podnoszeniem lub rzucaniem wyjątku. Dla dowolnej partii kodu możliwe jest zdefiniowanie bloku obsługi, który przechwytuje (ang. catch) określone rodzaje wyjątków. Poniżej widoczna jest typowa realizacja w pseudokodzie:
operacje programu
try operacje programu jeśli wystąpiła sytuacja wyjątkowa: throw wyjątek operacje programu catch wyjątek obsłuż wyjątek end
operacje programu
W momencie wykonania instrukcji throw sterowanie przekazywane jest do bloku catch, w którym powinien być zawarty kod obsługi danego rodzaju wyjątku. Po obsłużeniu, sterowanie nie powraca już do bloku try – program wykonuje się dalej od instrukcji end, zatem dalsze operacje wewnątrz tego bloku nie będą wykonywane. Zezwala się na rzucanie wyjątków z wnętrza funkcji, a także na zagnieżdżanie bloków try. W momencie wystąpienia wyjątku sterowanie jest przekazywane do pierwszego z nich, który potrafi go obsłużyć.
Istotnym problemem w obsłudze wyjątków jest to, że wewnątrz bloku try mogły zostać tymczasowo zaalokowane jakieś zasoby, które po zakończeniu wykonywania powinny zostać zwolnione. Jeśli rzucanie i przechwytywanie wyjątku zachodzi w obrębie tej samej funkcji, odpowiedni kod można umieścić za sekcją try ... catch, lecz funkcja rzuca wyjątek, który powinien przechwycić kod wywołujący, programista sam musi zadbać, by zwolnić wszystkie tymczasowe zasoby przed jego rzuceniem. Dlatego w niektórych językach wprowadzony jest dodatkowy, opcjonalny blok finally, który musi się wykonać niezależnie od tego, czy wewnątrz try został rzucony wyjątek, czy nie. Poniżej przedstawiony jest przykład w pseudokodzie ilustrujący zagadnienie:
procedura foo() try zaalokuj zasób X operacje programu jeśli wystąpiła sytuacja wyjątkowa: throw wyjątek operacje programu finally zwolnij zasób X end koniec
try wywołaj foo() catch wyjątek obsłuż wyjątek end
Na samym początku procedury foo()
alokujemy pewien zasób X, który musi zostać zwolniony przed zakończeniem jej wykonywania. Jednak w międzyczasie może zostać rzucony wyjątek, który w normalnych okolicznościach spowodowałby opuszczenie procedury i pojawienie się wycieku pamięci. Dlatego kod procedury zostaje objęty blokiem try z dołączoną klauzulą finally opisującą zwolnienie zasobów. Język programowania gwarantuje nam, że zostanie ona wykonana zarówno wtedy, gdy procedura zakończy się normalnie, jak i gdy zostanie rzucony wyjątek, który obsługiwany jest przez kod ją wywołujący.
Reprezentacja wyjątków jest zależna od konkretnego języka programowania. Przykładowo, w C++ wyjątkiem może być wartość dowolnego typu:
try
{
throw 20;
}
catch(int x)
{
cout << "Wystąpił wyjątek o kodzie " << x;
}
W Javie wyjątki mogą być wyłącznie obiektami klas rozszerzających klasę Throwable
:
try
{
throw new Exception("Informacja o błędzie");
}
catch(Exception x)
{
System.err.println(x.getMessage());
}
Skuteczność obsługi błędów zależy od przyjętej strategii obsługi wyjątków. Jednym z największych wyzwań jest konieczność przekazywania informacji o wyjątkach między systemami. Aplikacje biznesowe mogą składać się z wielu niewielkich programów oraz być rozproszone pomiędzy kilka maszyn, co wymaga podjęcia decyzji czy dany wyjątek powinien być obsługiwany w ramach aktualnego procesu czy przekazany do innej części systemu.
O kodzie powiemy, że jest bezpieczny dla wyjątków (ang. exception-safe), jeśli rzucenie wyjątku w jego obrębie nie produkuje niepożądanych skutków ubocznych takich, jak wycieki pamięci, generowanie nieprawidłowego wyniku czy pozostawienie systemu w stanie niespójnym. Kod bezpieczny dla wyjątków musi spełniać niezmienniki nawet w przypadku wystąpienia błędu. Wyróżniamy kilka poziomów bezpieczeństwa[1]:
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.