Obsługa błędów

Transkrypt

Obsługa błędów
Obsługa błędów
Rakieta Ariane 5 spadła 40 sekund po starcie. Straty 0,5
miliarda dolarów.
Przyczyna: wyjątek (exception) rzucony przez kod napisany
pierwotnie dla Ariane 4 . Feralna procedura była
niepotrzebna w trakcie lotu. Wyniki obliczeń przekroczyły
zakres typu short int dla większej rakiety (5) wywołując
wyjątek overflow. Nie przewidziano procedury obsługi tego
przypadku poniewaŜ nie „było szans” jego wystąpienia. W
Ariane 5 spowodowało to jednak zakończenie programu. Po
załamaniu programu sterującego zostały uruchomione
komputery zastępcze, ale wszystkie wdraŜały ten sam
program ...
Obsługa błędów
• Często niedoceniana i „spychana” na
dalszy plan (etap) realizacji projektu
• W obsłudze błędów trudno wykazać się
kreatywnością, polotem etc.
• Kod związany z obsługą błędów nie wnosi
nowych elementów do programu
• Powinna być rutynowa, metodyczna...
(czyli nudna)
Konwencje obsługi błędów
Stosowano róŜne schematy obsługi błędów: Funkcje
zwracają kod błędu (Visa Library)
Ustawiają specjalną flagę (iberr – NI GPIB library)
Takie rozwiązania prowadzą do kodu, w którym funkcje
podstawowe i obsługa błędów są „przemieszane” i tym
samym słabo czytelne, a ponadto formalnie nie zmuszają
programisty do reakcji na te błędy w myśl zasady; „błędy
przytrafiają się innym, nie mnie”
Obecnie stosowana koncepcja obsługi wyjątków wywodzi
się z rozwiązań stosowanych w systemach operacyjnych
w latach „60”, „on error goto” Basica i przez języki Ada
oraz C++ trafiła do Javy
Exception handling
• "Anything that can go wrong will go
wrong."
• An exception handler can return to the
instruction that generated the problem
This is a dangerous facility to give to an
application program
• An exception always "abruptly terminates"
a statement or sequence of statements in
a block and exits to an outer block of code
Definicja
€ Wyjątek (Exception) to zdarzenie
występujące w trakcie wykonania
programu, które przerywa normalny tok
wykonywania instrukcji.
• W miejscu wystąpienia problemu nie
wiadomo co zrobić, nie moŜna zatem
kontynuować działania naleŜy je przerwać
i przekazać decyzję co dalej robić na
wyŜszy poziom
Przyczyny
• Wiele źródeł błędów moŜe powodować powstanie
wyjątków poczynając od uszkodzeń sprzętowych takich
jak awaria dysku, do prostych błędów programowych jak
próba odwołania do indeksu tablicy wykraczająca poza
jej rozmiar. Jeśli taki błąd powstanie wewnątrz metody
kreowany jest obiekt wyjątku i przekazywany do systemu
wykonania. Obiekt ten zawiera informację o swoim typie
i stanie programu, kiedy powstał błąd. System wykonania
jest odpowiedzialny za znalezienie kodu obsługi tego
błędu. W Javie tworzenie obiektu wyjątku i przekazanie
go do systemu wykonania określane jest jako rzucanie
wyjątku (throwing an exception).
Przechwytywanie wyjątków
• Sekwencja wywołania metod przechowywana
jest na stosie. System wykonania rozpoczyna
poszukiwanie metody, która posiada
odpowiednią procedurę obsługi wyjątku
(exception handler) poczynając od metody w
której powstał wyjątek w kolejności odwrotnej
do sekwencji wywoływania metod. Odpowiednia
procedura to taka, która obsługuję wyjątek
danego typu. O takiej procedurze mówi się, Ŝe
„przechwyciła” wyjątek. Jeśli system wykonania
nie znajdzie odpowiedniej procedury obsługi
program kończy działanie.
To dla mnie sytuacja wyjątkowa
• NajpowaŜniejszą zaletą takiego podejścia jest
moŜliwość separacji kodu realizującego główne
funkcje programu z obsługą potencjalnych
błędów.
• Sytuacja wyjątkowa to taka, w której nie
moŜemy kontynuować programu poniewaŜ nie
mamy w bieŜącym kontekście wystarczających
danych i jedyne co moŜemy zrobić to przerwać
wykonanie tego kontekstu i przekazać
sterowanie na zewnątrz do procedury obsługi (na
wyŜszy poziom).
Rzucanie wyjątku
SomeType metoda(Object t) {
if(t == null)
throw new NullPointerException();
// ...
}
Uwagi:
1. Mamy całą hierarchię klas „wyjątkowych”, której
wierzchołkiem jest klasa Throwable i możemy definiować
„własne” wyjątki
2. throw new NullPointerException("t = null"); // 2gi
konstruktor
3. metoda „zwraca” obiekt wyjątku! A nie obiekt SomeType
Instrukcja throw
• Instrukcja throw jest rodzajem skoku, który
przekazuje sterowanie do odpowiedniej części
catch w bieŜącej metodzie bądź metodzie
wywołującej ją ...
• Metoda, w czasie wykonania której moŜe dojść
do sytuacji wyjątkowej (błędu) deklaruje to
przez uŜycie throws
void f() throws TooBig, TooSmall, DivZero { //...
Kompilator, jeśli uŜyjemy metody deklarującej
rzucanie wyjątku forsuje nas do jego obsługi
Uwaga:Nie dotyczy to RuntimeException
Region „chroniony”
try {
// Code that might generate exceptions
} catch(Type1 id1) {
// Handle exceptions of Type1
} catch(Type2 id2) {
// Handle exceptions of Type2
} catch(Type3 id3) { // Handle exceptions of Type3
}
// etc...
Uwaga: Sterowanie jest przekazywane do pierwszej
procedury obsługi wyjątku zgodnej z typem i uznaje się że
wyjątek został obsłużony!
Sprzątanie - finally
try {
// The guarded region: Dangerous activities
// that might throw A, B, or C
} catch(A a1) {
// Handler for situation A
} catch(B b1) {
// Handler for situation B
} catch(C c1) {
// Handler for situation C
} finally {
// Activities that happen every time
}
MoŜna „oszukać” kompilator?
• Jeśli kod wewnątrz metody moŜe spowodować wyjątek, a
nie dostarczymy procedury jego obsługi zostaniemy
„zdyscyplinowani” przez kompilator
try {
// Code that might generate exceptions
} catch(Type1 id1) {
// Handle exceptions of Type1 }
lub moŜemy przekazać obsługę na wyŜszy poziom
SomeType metoda () throws Type1 {
// Code that might generate exceptions
}
MoŜna ale ...
SomeType metoda () throws Type1 {
// Code that does not generate any exceptions
// ale będzie, tylko Ŝe teraz skupiamy się na głównym //zadaniu
metody
// rozwiązujemy zadanie jak wszystko jest ok później dołączymy kod
typu:
// „if something will go wrong”
}
Uwaga: Podobne podejście zastosujemy w klasach abstrakcyjnych i
w interfejsach
Termination vs resumption
In termination you assume that the error is so critical
that there’s no way to get back to where the
exception occurred. Whoever threw the exception
decided that there was no way to salvage the
situation, and they don’t want to come back.
W Javie (podobnie jak w C++) obowiązuje zasada, Ŝe nie ma
moŜliwości (sensu) ponowienia wykonania kodu, który rzucił
wyjątek. Jeśli uwaŜasz, Ŝe procedura obsługi wyjątku moŜe coś
naprawić, co umoŜliwi kontynuowanie wykonania metody nie
rzucaj wyjątku ale wywołaj procedurę naprawczą!
MoŜna teŜ umieścić try-catch blok w pętli...
Własne klasy wyjątków
class MyException2 extends Exception {
private int x;
public MyException2() {}
public MyException2(String msg) { super(msg); }
public MyException2(String msg, int x) {
super(msg); this.x = x; }
public int val() { return x; }
public String getMessage() { return "Detail Message: "+ x + "
"+
super.getMessage();
}
}

Podobne dokumenty