temat 10 - Robert Arsoba

Transkrypt

temat 10 - Robert Arsoba
Materiały dydaktyczne
Języki i paradygmaty programowania
Wyjątki
(obsługa sytuacji wyjątkowych)
dr inż. Robert Arsoba
[email protected]
Koszalin 2012
Wersja 1.0
KIK 2012
Sytuacje wyjątkowe w programach
Strona 2
Powody sytuacji wyjątkowych:
• błąd w programie
• niepoprawne dane wejściowe
• niepoprawne działanie sprzętu
przyczyny wewnętrzne
przyczyny zewnętrzne
Języki i paradygmaty programowania
Obsługa błędów:
• zakończenie programu z komunikatem o błędzie
– funkcja exit (kod błędu)
• „bezpieczne” zakończenie programu
– zapis danych
– zwolnienie zasobów (pamięć, pliki, strumienie, itd…)
• kontynuacji działania programu
– próba naprawienia błędu
– próba „obejścia” błędu
– rezygnacja z części funkcjonalności programu
KIK 2012
Przykłady sytuacji wyjątkowych
Strona 3
Przykład 1
Dzielenie przez zero
int a = 5;
int b = 0;
int c;
Języki i paradygmaty programowania
Rozwiązanie: wykrywanie błędu
if (b == 0)
// ...
c = a / b;
Runtime error
KIK 2012
Przykłady sytuacji wyjątkowych
Strona 4
Przykład 2
Języki i paradygmaty programowania
Przepełnienie zmiennej
int silnia(unsigned int n)
{
if (n > 12)
Rozwiązanie
return 0;
unsigned int wynik = 1;
for (int i = 1; i <= n; i++ )
wynik = wynik * i;
return wynik;
}
double silnia(unsigned int n)
{
double wynik = 1;
for (int i = 1; i <= n; i++ )
wynik = wynik * i;
return wynik;
}
Błędny wynik
obliczeń
KIK 2012
Przykłady sytuacji wyjątkowych
Strona 5
Przykład 3
Błąd otwarcia pliku
FILE *plik;
Języki i paradygmaty programowania
plik = fopen(”nazwa.txt”, ”r”);
if (plik == NULL)
{
cout << ”Błąd otwarcia pliku” << endl;
exit(1);
}
Rozwiązanie
Odczytywanie
z nieotwartego
pliku
KIK 2012
Przykłady sytuacji wyjątkowych
Strona 6
Przykład 4
Języki i paradygmaty programowania
Brak pamięci
int *tablica;
int n;
cin >> n;
tablica = malloc(n*sizeof(int));
if (tablica == NULL)
{
cout << ”Brak pamięci” << endl;
exit(1);
}
Rozwiązanie
tablica = new int[n];
if (tablica == NULL)
{
cout << ”Brak pamięci” << endl;
exit(1);
}
Odwoływanie się
do zabronionego
obszaru
pamięci
KIK 2012
Przykłady sytuacji wyjątkowych
Strona 7
Przykład 5
Przekroczenie zakresu
int tablica[5];
Języki i paradygmaty programowania
for (int i = 0; i < 10; i++)
tablica[i] = i;
Odwoływanie się
do zabronionego
obszaru
pamięci
KIK 2012
Wyjątki w C++
Strona 8
Wyjątkiem (ang. exception) w C++ może być wartość dowolnego typu
(prostego, obiektowego, …).
Języki i paradygmaty programowania
Funkcja, która wykryje błąd i nie obsługuje go (lub nie jest w stanie go
obsłużyć) generuje (rzuca) wyjątek.
Wygenerowanie (rzucenie) wyjątku powoduje natychmiastowe przerwanie
wykonywania funkcji.
Funkcja wywołująca może przechwycić (złapać) wyjątek.
Nieprzechwycony (niezłapany) wyjątek powoduje przerwanie wykonywania
programu – nie należy ignorować wyjątków.
KIK 2012
Nowe słowa kluczowe
Strona 9
Z wyjątkami związane są następujące polecenia (tzw. klauzulue):
try – polecenie, po którym umieszczamy instrukcje, które mogą
potencjalnie wygenerować (rzucić) wyjątek
Języki i paradygmaty programowania
catch – polecenie przechwytujące wyjątek
– można używać kilku poleceń catch do łapania wyjątków
(sterowanie programem jest przekazywane do polecenia,
które odpowiada wygenerowanemu wyjątkowi)
throw – polecenie rzucające wyjątek
– umożliwia także zadeklarowanie listy wyjątków rzucanych
przez funkcję
KIK 2012
Przykład
Strona 10
Języki i paradygmaty programowania
#include <iostream>
#include <cstdlib>
using namespace std;
class liczba
{
public:
liczba(int x = 0) : wartosc(x)
{ cout << "tworzenie obiektu: " << wartosc << endl; }
~liczba()
{ cout << "niszczenie obiektu " << wartosc << endl; }
private:
int wartosc;
};
void fun()
{
liczba a(1);
throw 0; // wygenerowanie wyjatku
//throw 0.0; // wygenerowanie wyjatku
cout << "efekt uruchomienia funkcji" << endl;
}
KIK 2012
Języki i paradygmaty programowania
Przykład
Strona 11
int main()
{
liczba b(2);
try
{
liczba c(3);
fun();
cout << "efekt polecenia try" << endl;
}
catch (double)
{
cout << "przechwycono double" << endl;
}
catch (int)
{
cout << "przechwycono int" << endl;
}
catch (...) // każdy wyjątek
{
cout << "przechwycono COŚ" << endl;
}
cout << "efekt dzialania main" << endl;
return 0;
}
Przed kaluzulami
catch wywołane
zostaną destruktory
tworzenie obiektu 2
tworzenie obiektu 3
tworzenie obiektu 1
niszczenie obiektu 1
niszczenie obiektu 3
przechwycono
int
efekt działania main
KIK 2012
Przykład – nieprzechwycone wyjątki
Strona 12
Nieprzechwycenie wyjątku powoduje wywołanie funkcji systemowej
terminate(), która następnie wywołuje funkcję abort().
Definiowanie własnej funkcji terminate:
Języki i paradygmaty programowania
namespace std
{
typedef void (*terminate_handler)(void);
terminate_handler set_terminate(terminate_handler NaszTerminate);
}
void NaszTerminate()
{
std::cerr << "zatrzymanie programu" << std::endl;
exit(1);
Własna funkcja terminate musi kończyć się
}
wywołaniem funkcji exit lub abort.
main()
{
std::set_terminate(NaszTerminate);
throw 0;
}
KIK 2012
Deklaracja wyjątków rzucanych przez funkcję
Strona 13
void funkcja1() throw()
{ }
// nie rzuca żadnych wyjątków
void funkcja2() throw(exception)
{ }
Języki i paradygmaty programowania
void funkcja3()
{ }
// rzuca wyjątki tylko ze
// standardowej hierarchii
// rzuca dowolne wyjątki
Jeżeli funkcja rzuca wyjątek, który nie został zadeklarowany na liście
wyjątków w nagłówku funkcji, to wywołana zostaje funkcja
systemowa unexpected(), która domyślnie wywołuje abort().
Definiowanie własnej funkcji unexpected:
void unexpected_handler()
{
throw 0; // np. rzucanie int
};
std::set_unexpected(unexpected_handler);
KIK 2012
Hierarchia wyjątków
Strona 14
Języki i paradygmaty programowania
Hierarchia klas wyjątków w bibliotece standardowej
KIK 2012
Korzystanie z hierarchii wyjątków
Strona 15
Nieprzechwycenie wyjątku powoduje wywołanie funkcji systemowej
terminate(), która następnie wywołuje funkcję abort().
main()
{
try
{
Języki i paradygmaty programowania
throw domain_error();
}
catch(invalid_argument &e)
{
cout << e.what() << endl;
}
Wykonywana jest pierwsza
klauzula catch, która pasuje
do wygenerowanego wyjątku
Wyjątki należy przechwytywać
przez referencję.
catch(logic_error &e)
{
cout << "logic " << e.what() << endl;
}
catch(exception &e)
{
cout << "jakis wyjatek " << e.what() << endl;
}
}
KIK 2012
Wyjątki
Strona 16
Z przymrużeniem oka… czyli po co jest try i catch?
„Błądzić jest rzeczą ludzką.” (Seneka Starszy)
„Błędów nie popełnia ten, kto nic nie robi.” (Theodore Roosevelt)
Języki i paradygmaty programowania
„Najczęstszy ludzki błąd – nie przewidzieć burzy w piękny czas.”
(Niccolo Machiavelli)
„Prawdziwym błędem jest błąd popełnić i nie naprawić go.” (Konfucjusz)
„Popełniaj błędy i naprawiaj je” (Myslovitz: „Acidland”)
„Najlepszych ludzi uformowało naprawianie własnych błędów.”
(William Shakespeare)
„Żył jako błąd, poprawiony umarł.” (Andrzej Coryell)
„Najwyższą formą zaufania jest kontrola.”

Podobne dokumenty