Efekty uboczne błędów



Podobne dokumenty
Klasyfikacja wyjątków

Wyjątki (exceptions)

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

Język C++ wykład VIII

Obsługa wyjątków. Język C++ WW12

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Programowanie w języku C++

Throwable. Wyjatek_1(int x_) { x = x_; } int podaj_x()

Zaawansowane programowanie w języku C++ Wyjątki

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

WYJĄTKI. Jest ona jednak czasochłonna i prowadzi do duŝego zapotrzebowania na zasoby systemu.

Języki i metody programowania Java INF302W Wykład 3 (część 1)

Programowanie Obiektowe Ćwiczenie 4

Programowanie w języku C++

Wstęp do programowania

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Wyjątki Monika Wrzosek (IM UG) Programowanie obiektowe 180 / 196

Wykład 8: Obsługa Wyjątków

1 Kursory 1. 2 Wyjątki Wyjątki predefiniowane Wyjątki niezdefiniowane wcześniej Definiowanie własnych wyjątków...

PARADYGMATY PROGRAMOWANIA Wykład 4

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

Zad.30. Czy można utworzyć klasę, która implementuje oba interfejsy?

ATD. Wykład 8. Programowanie (język C++) abstrakcyjny typ danych. Abstrakcyjne typy danych (ATD) Metody czysto wirtualne. Definicje i uwagi:

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Oracle PL/SQL. Paweł Rajba.

Klasy cd. Struktury Interfejsy Wyjątki

Delphi Laboratorium 3

Klasy generyczne. ZbiórLiczb. ZbiórCzegokolwiek. Zbiór

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

DYNAMICZNE PRZYDZIELANIE PAMIECI

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Szablony klas, zastosowanie szablonów w programach

Programowanie obiektowe

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Aplikacje w środowisku Java

Zaawansowane programowanie w języku C++ Klasy w C++

Programowanie 2. Język C++. Wykład 3.

Podstawy programowania w języku C++

Obsługa błędów za pomocą wyjątków. Paweł Motofa (140746)

Szablony funkcji i klas (templates)

Abstrakcyjny typ danych

Ada-95. Dariusz Wawrzyniak

Język PL/SQL. Rozdział 3. Obsługa błędów wykonania Wyjątki predefiniowane i użytkownika, zgłaszanie i obsługa wyjątków.

Programowanie w języku C++

Szablony funkcji i szablony klas

Wstęp do programowania

Szablony. Szablony funkcji

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Wstęp do Programowania 2

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Wykład 8: klasy cz. 4

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

kiedy znowu uzyska sterowanie, to podejmuje obliczenie od miejsca, w którym poprzednio przerwała, i z dotychczasowymi wartościami zmiennych,

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Programowanie obiektowe

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

Lab 9 Podstawy Programowania

Programowanie obiektowe

Składnia C++ Programowanie Obiektowe, część 3 Mateusz Cicheński

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

PARADYGMATY PROGRAMOWANIA Wykład 3

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Języki programowania

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

ZASADY PROGRAMOWANIA KOMPUTERÓW

Programowanie obiektowe

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Definicje klas i obiektów. Tomasz Borzyszkowski

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Podstawy programowania w języku C++

Materiały do zajęć III

Zaawansowane programowanie w C++ (PCP)

Programowanie obiektowe w C++ Wykład 12

Listy powiązane zorientowane obiektowo

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Język C++ zajęcia nr 2

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Wyjątki. Wyjątki. Wyjątki. Wyjątki. Wyjątki. Wyjątki

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Język C++ Różnice między C a C++

Skrypty i funkcje Zapisywane są w m-plikach Wywoływane są przez nazwę m-pliku, w którym są zapisane (bez rozszerzenia) M-pliki mogą zawierać

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Podstawy Programowania Obiektowego

Wprowadzenie do szablonów klas

Stos liczb całkowitych

Programowanie Obiektowe i C++

Tablice, funkcje - wprowadzenie

Transkrypt:

Obsługa wyjątków

Efekty uboczne błędów Fragment kodu programu jest bezpieczny (ang. exception-safe) jeżeli błędy, które wystąpią w trakcie przetwarzania tego kodu nie będą powodowały niepożądanych efektów ubocznych: niezwalnianie zasobów: pamięci operacyjnej, systemu plików, procesów, sesji programów systemowych, kursorów, itp.; zmienione wartości danych: nieukończone poprawnie przetwarzanie kodu pozostawia jednak zmienione wartości danych, np. zmieniony stan obiektów; niespełnienie zdefiniowanych niezmienników: po fiasku przetwarzania stan zasobów i danych jest niepoprawny, np. wskaźnik stosu jest niespójny z liczbą elementów na stosie; błędny wynik działania kodu: wynik działania programu jest niepoprawny.

Bezpieczeństwo kodu Można wyróżnić pięć podstawowych typów bezpieczeństwa kodu: 1. Odporność na błędy przetwarzanie kodu zawsze kończy się poprawnie. 2. Wysoki poziom bezpieczeństwa fiasko przetwarzania nie powoduje żadnych efektów ubocznych, dzięki czemu dany program może dalej działać. 3. Podstawowy poziom bezpieczeństwa - fiasko przetwarzania może pozostawić zmienione wartości danych, ale zdefiniowane niezmienniki są zachowane. 4. Minimalny poziom bezpieczeństwa fiasko przetwarzania może pozostawić niepoprawne wartości danych, ale zwolnione są wszystkie przydzielone zasoby, dzięki czemu można zamknąć działanie programu. 5. Brak bezpieczeństwa fiasko przetwarzania nie daje żadnych gwarancji poprawności

Przykłady obsługi wyjątków Jaki jest poziom bezpieczeństwa poniższej klasy? template <class T> class Stack { unsigned nelems; int top; T* v; public: void push(t); T pop(); Stack(const Stack&); Stack& operator=(const Stack&); ~Stack(); ; template void Stack::push(T element) { top++; if( top == nelems-1 ){ T* new_buffer = new T[nelems+=10]; if( new_buffer == 0 ) throw OutOfMemory(); for(int i = 0; i < top; i++) new_buffer[i] = v[i]; delete [] v; v = new_buffer; v[top] = element;

Przykłady obsługi wyjątków Przykład efektów ubocznych procedury obsługi wyjątków: template <class T> class Stack { unsigned nelems; int top; T* v; public: void push(t); T pop(); Stack(const Stack&); Stack& operator=(const Stack&); ~Stack(); ; template void Stack::push(T element) { top++; if( top == nelems-1 ){ T* new_buffer = new T[nelems+=10]; if( new_buffer == 0 ) // pozostawienie zmienionych i niespójnych danych throw OutOfMemory(); for(int i = 0; i < top; i++) new_buffer[i] = v[i]; delete [] v; v = new_buffer; v[top] = element;

Cele obsługi błędów Dwie podstawowe strategie: Unikanie degradacji systemu: Zadania, w których pojawiły się błędy, powinny być jak najszybszej wykryte i przerwane w celu uniknięcia propagacji błędów do innych powiązanych zadań. Zakończenie zadania powinno być poprzedzone odtworzeniem poprawnego stanu środowiska sprzętowo-programowego (fail-fast J. Grey, zorganizowana panika B. Meyer). Odporność na błędy: Fiasko wykonywania jakiegoś modułu powoduje wycofanie wyników jego działania i powtórne uruchomienie tego samego lub alternatywnego modułu przy zmienionych warunkach wejściowych. Powyższe cele mogą być osiągane łącznie. Na niższych poziomach działania programu - unikanie degradacji, na wyższych - odporność na błędy.

Architektura procedur obsługi wyjątków Zagnieżdżone wywołan nia metod tworzą stos wy- szukiwaniaa procedur obsługi błędów.

Podstawowe lokalne schematy obsługi wyjątków Budowa modułów programowych wielokrotnego użytku wymaga stosowania uniwersalnych schematów obsługi błędów. Funkcjonalność obsługi wyjątków powinna zawierać następujące kroki: 1. Przywrócenie stanu spójnego przez wycofanie/kompensację wprowadzonych zmian i zwolnienie przydzielonych zasobów 2. Zgłoszenie/przekazanie wyjątku do miejsca wywołania modułu, który wyłapał wyjątek 3. Zmiana warunków i ponowne wywołanie kodu, który zgłosiła wyjątek Unikanie degradacji działającego programu powinno obejmować kroki 1) i 2), dalsze działanie programu wymaga zastosowania kroków 1) i 3). Brak wykonania kroku 1) pociąga za sobą konieczność zatrzymania pracy programu. Praca programu nie może być kontynuowana przy pozostawieniu niespójnych danych.

Jak nie należy obsługiwać wyjątków Przykład z podręcznika języka ADA sqrt (n: REAL) return REAL is begin if x < 0.0 then raise Negative else wyliczenie pierwiastka end exception when Negative => put("negative argument") -- komunikat return -- powrót bez zgłoszenia błędu when others => end -- sqrt m 0 call m1 niepowiadomienie modułu wywołującego o błędzie return OK call m 1 exception put() return zgłoszenie wyjątku obsługa wyjątku nie obejmująca funkcjonalności m1

Jak nie należy obsługiwać wyjątków Zamykanie działania całego programu przez zagnieżdżone moduły. Moduł wielokrotnego użytku nie zna kontekstu swojego wywołania. sqrt (n: REAL) return REAL is begin if x < 0.0 then raise Negative end exception when Negative => put("negative argument") -- komunikat exit zamknięcie działania programu when others => end -- sqrt m 0 call m1 call m 1 exception exit zgłoszenie wyjątku Zamknięcie programu

Typy wyjątków Fiasko wykonywania program: wykonywanie programu nie może być kontynuowane Czas wykonywania programu przekroczył założone granice czasowe Niedostępność zasobów: żądanie przydziału zasobów nie może być zrealizowane Zewnętrzne przerwanie przetwarzania: zewnętrzne moduły programowe lub użytkownicy przerywają wykonywanie programu Naruszenie zdefiniowanych ograniczeń: wykonywanie programu narusza przyjęte niezmienniki, warunki początkowe lub końcowe

Wsparcie obsługi wyjątków przez języki programowania 1. Rozdzielenie w strukturze programów przepływu sterowania dla normalnej pracy programu i dla obsługi wyjątków 2. Mechanizm zgłaszania wyjątków: jawnie przez programistów lub niejawnie przez środowisko sprzętowo-programowe. Obydwa rodzaje wyjątków powinny być obsługiwane w jednorodny sposób. 3. Mechanizm dla przekazywania sterowania do procedur obsługi błędów w przypadku zgłoszenia wyjątku. Powinny być zdefiniowane reguły przypisujące każdemu wyjątkowi określoną procedurę obsługi wyjątku. 4. Mechanizm umożliwiający zdefiniowanie zachowania programu po zakończeniu obsługi wyjątku na jeden z dwóch sposobów: podjęcie akcji dla zakończenia pracy systemu, lub ponowne wykonanie przerwanych operacji. 5. Powiązanie mechanizmu obsługi wyjątków z asercjami klas. Większość języków programowania nie wspiera podstawowych schematów obsługi wyjątków.

Model obsługi wyjątków w C++ Dodatkowa składnia służąca do przekazywania sterowania i danych do wyodrębnionych procedur obsługi wyjątków. 1. Definicja wyjątku Wyjątek może być zdefiniowany jako: typ prosty ograniczona liczba wyjątków typ wyliczeniowy ograniczona taksonomia wyjątków klasa Język C++ nie wspiera obsługi wyjątków systemowych 2. Zgłoszenie wyjątku Throw wyjątek parametr aktualny 3. Wyłapanie wyjątku Kod, która ma wyłapywać zgłoszone wyjątki musi znajdować się w trybie nasłuchiwania: try { // nasłuchiwanie catch(wyjątek) - parametr formalny 4. Obsługa wyjątku Procedura realizująca wybrana strategie obsługi wyjątków

Obsługa wyjątków Przykład obsługi wyjątków: class Tablica { int rozmiar; int *ip; public: class Zakres { ; // definicja klasa wyjątku Tablica (int roz) {ip = new int[rozmiar=roz];; int& operator[](unsigned); ~ Tablica ( ) { delete ip; ; int& Tablica::operator[] (int indeks) { if (indeks >= 0 && indeks < rozmiar) return ip[indeks]; else throw Zakres( ); W tym wypadku wyjątek jest pustą klasą bez zmiennych i metod. Informację niesie typ klasy. Wywołanie konstruktora klasy Zakres // zgłoszenie wyjątku void main(void) { n=21; Tablica t1(12); try { // nasłuchiwanie wyjątków zakresu for (int i=0; i<n; i++ ) t1[i] = 2*i + 1; Wyłapanie wyjątku na podstawie jego typu catch (Tablica::Zakres) // wyłapywanie wyjątku { // procedura obsługi wyjątku cout << "Przekroczenie zakresu" << endl; // i jeszcze coś sensownego!

Wyjątki zwracające informacje W tym wypadku wyjątki są klasami niosącymi dodatkowe informacje class Tablica { class Zakres { // definicja wyjątku public: int indeks; Zakres(int ind) { indeks = ind; ; class Rozmiar { // definicja wyjątku public: int rozmiar; Rozmiar(int rozm) {rozmiar = roz; ; ; Tablica::Tablica (int roz) { if (roz >= 0 && roz <= MaxRozmiar) ip = new int[rozmiar=roz] else throw Rozmiar(roz); /* zwrócenie wartości przez z definicji beztypowy konstruktor */ try { // tworzenie tablic i operowanie na tablicach catch (Tablica::Rozmiar r) {//parametr formalny cout << "Zły rozmiar tablicy: " << r.rozmiar<< endl; catch (Tablica::Zakres z) { cout<<"przekroczenie zakresu: "<<z.indeks << endl;

Wyjątki, a klasy generyczne Różne wyjątki dla różnych wystąpień klasy wzorca template<class T> class Tablica { class Zakres { ; ; try { Tablica<int> ti(24); Tablica<float> tf(12); catch(tablica<int>::zakres) { catch(tablica<float>::zakres) { Definicja wyjątku wspólnego dla wszystkich wystąpień klasy wzorca class Zakres { ; template<class T> class Tablica { ; try { Tablica<int> ti(24); Tablica<float> tf(12); catch(zakres) { Zdefiniowanie wyjątku jako klasy zagnieżdżonej wewnątrz klasy generycznej pozwala na rozróżnienie różnych wystąpień klasy generycznej.

Typy wyliczeniowe: Klasyfikacja wyjątków enum BłądMatemat {Nadmiar, Niedomiar, ; try { catch (BłądMatemat bm) { switch (bm) { case Nadmiar: case Niedomiar: Hierarchia wyjątków: Zdefiniowanie zbioru wyjątków jako hierarchii klas umożliwia ich elastyczną obsługę: unikalne metody obsługi poszczególnych wyjątków lub wspólną obsługę wielu typów wyjątków. class BłądMatemat { ; class Nadmiar: public BłądMatemat { ; class Niedomiar: public BłądMatemat { ; try { catch (Nadmiar) { // obsługa błędu Nadmiar catch (BłądMatemat bm) {//polimorficzne dopasowanie wyjątku // obsługa błędów matematycznych, innych niż Nadmiar

Polimorficzna obsługa wyjątków Hierarchia wyjątków: class BłądMatemat { virtual informacja_o_błędzie() {; ; class Nadmiar: public BłądMatemat { protected: const char* operacja; int operand1; int operand2; public: virtual informacja_o_błędzie() { // wykorzystuje zdefiniowane lokalnie zmienne ; ; try { catch (BłądMatemat bm) { bm.informacja_o_błędzie(); /* wiązanie statyczne informacje specyficzne dla błędu nadmiaru są niedostępne */ try { catch (BłądMatemat& bm) { // wiązanie dynamiczne bm.informacja_o_błędzie();

Specyficzne konstrukcje obsługi wyjątków Wyrażenie throw umieszczone w procedurze obsługi błędów i nie posiadające argumentu, oznacza ponowne zgłoszenie wyłapanego wyjątku. try { catch (Nadmiar) { // częściowa obsługa błędu Nadmiar throw; //ponowne zgłoszenie wyjątku Nadmiar catch (BłądMatemat bm) { /* częściowa obsługa błędów matematycznych, innych niż Nadmiar */ throw; //ponowne zgłoszenie wyjątku BłądMatemat catch () { // "" oznacza dowolny argument /* obsługa wszystkich pozostałych wyjątków */ Specyficznym typem formalnym wyrażenia wyłapującego wyjątki jest typ: " ". Oznacza on dowolny typ wyjątku. Umieszczenie wyrażenia catch( ) na końcu kodu obsługi błędów gwarantuje wyłapywanie wszystkich wyjątków.

Specyfikacja wyjątków w deklaracji klasy Specyfikacja wyjątków zgłaszanych przez klasę jest częścią deklaracji klasy. Wiedza o wyjątkach zgłaszanych przez klasę jest niezbędna do poprawnego korzystania z wystąpień danej klasy. 1. Funkcja/metoda funkcja1 może zgłosić jedynie wyjątki: Zakres i BłądMatemat: void funkcja1 (const Tablica& ) throw(tablica::zakres, BłądMatemat); 2. Funkcja/metoda funkcja2 może zgłosić każdy wyjątek: void funkcja2 (const Tablica& ); 3. Funkcja/metoda funkcja3 nie zgłasza żadnych wyjątków: void funkcja3 (const Tablica& ) throw( );

Funkcje związane z obsługą wyjątków 1. Nieoczekiwane wyjątki Funkcja unexpected() jest wywoływana jeśli funkcja z wyspecyfikowaną listą wyjątków zgłasza wyjątek spoza tej listy. Funkcja unexpected() domyślnie wywołuje funkcję terminate(). Programista może samodzielnie zdefiniować znaczenie funkcji unexpected() za pomocą funkcji set_unexpected() 2. Nie wyłapane wyjątki Funkcja terminate() jest wywoływana kiedy: mechanizm obsługi wyjątków nie może znaleźć procedury obsługi dla zgłoszonego wyjątku; przed przejściem do obsługi wyjątku nastąpi uszkodzenie stosu; kiedy destruktor wywołany przed przejściem do obsługi wyjątku próbuje zgłosić wyjątek. Funkcja terminate() domyślnie wywołuje funkcję abort(). Programista może samodzielnie zdefiniować znaczenie funkcji terminate() za pomocą funkcji set_ terminate().

Wzorce obsługi wyjątków Zorganizowana panika: class klasa { try { throw Wyjątek_1( ); catch (Wyjątek_1) { // kompensacja wykonanych działań Throw Wyjątek_2( ); // zgłoś wyjątek do miejsca wywołania ; Odporność na błędy: class klasa { jeszcze_raz: try { throw Wyjątek( ); catch (Wyjątek_1) { // kompensacja wykonanych działań // zmiana warunków wywołania goto jeszcze_raz; ;

Obsługa wyjątków w języku Java W języku Java zintegrowano wyjątki systemowe i wyjątki definiowane przez użytkownika. Wszystkie wyjątki użytkowników muszą być bezpośrednimi lub pośrednimi wystąpieniami systemowej klasy Exception. Hierarchia klas wyjątków i błędów: class Throwable class Error class Exception class AssertionError class RuntimeException class ThreadDeath