Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria Informatica, Gestionale e dell’Automazione Lezione 8 Gestione delle eccezioni Fallimenti software Un sistema software può non essere in grado di compiere il suo dovere A causa di errori nella sua implementazione Per l’impossibilità di ottenere risorse esterne di cui ha bisogno Non si può rimediare agli errori di programmazione al momento dell’esecuzione, salvo cercare di fornire spiegazioni adeguate all’utente. Fallimenti dovuti a cause esterne Un sistema software può avere bisogno di risorse da Hardware Sistema operativo File system Rete Database Utente È possibile che tali risorse non siano disponibili o non siano adeguate Anomalie ed eccezioni Le eccezioni sono delle anomalie rilevabili al momento dell’esecuzione Divisione per 0 Accesso ad un elemento dell’array oltre i suoi limiti Esaurimento della memoria Dato ricevuto in input di un tipo non atteso Quando si verifica un evento eccezionale, la parte di programma che la rileva la può segnalare sollevando (lanciando) un’eccezione Gestione delle eccezioni La gestione delle eccezioni è un meccanismo tramite il quale una parte di un programma può segnalare un problema che verrà gestito altrove In una parte di un programma si verifica un problema che non è in grado di risolvere In un’altra parte del programma si sa come gestire il problema Tramite la gestione delle eccezioni si trasferisce il controllo della gestione degli eventi eccezionali Non è però un meccanismo di controllo come gli altri Gestione delle eccezioni Espressione throw Blocco try Segnala la presenza di un’anomalia che non si è in grado di gestire localmente L’espressione che segue la parola chiave throw è il tipo dell’espressione lanciata Definisce un campo d’azione locale e racchiude tutte le istruzioni che possono lanciare eccezioni Un blocco try termina con una o più clausole catch che catturano e gestiscono le eccezioni Classi exception Passano informazioni sull’errore da dove viene generato a dove viene gestito Lancio di eccezioni Un’eccezione si lancia con un’espressione throw Parola chiave throw seguita da un’espressione Alcune eccezioni, ad esempio runtime_exception, sono definite dalla libreria standard in stdexcept Generalmente l’operando è un oggetto che rappresenta l’eccezione È possibile che venga lanciata un’espressione anche dal blocco catch Un’eccezione non è una richiesta di terminazione di un programma In questo caso può essere gestita solo da un blocco try più esterno Ma un’eccezione non gestita causa la terminazione del programma Un throw senza argomenti causa la terminazione immediata del programma Salvo il caso di rilancio di un’eccezione Esempio: lancio di eccezione Razionale::Razionale(int num, int den) { n = num; if (den == 0) throw new runtime_error("il denominatore non può essere 0"); d = den; } Blocco try try { // codice che potrebbe lanciare eccezioni // es. throw exception; } catch(E1 ex) { // codice che gestisce le eccezioni di tipo E1 } catch(E2 ex) { // codice che gestisce le eccezioni di tipo E2 } Esempio: cattura di un’eccezione con try/catch int main() { try { Razionale r(2, 0); // … } catch(const runtime_error* e) { cerr << "Eccezione: " << e->what() << endl; } return 0; } Esempio: blocco try di funzione int main(int argc, char *argv[]) try { Razionale r(2, 0); return 0; } catch(const runtime_error* e) { cerr << "Eccezione: " << e>what() << endl; system("PAUSE"); return -1; } L’intero corpo della funzione è contenuto nel blocco try Separazione più netta tra il codice che implementa l’elaborazione normale e quello che supporta la gestione delle eccezioni Cattura di un’eccezione I gestori delle eccezioni sono contenuti nei blocchi catch catch (tipoEccezione eccezione) { //… } Cattura le eccezioni il cui tipo corrisponde a tipoEccezione catch(…) Cattura tutte le eccezioni Non conosciamo il tipo dell’eccezione catturata Non ha parametri, non possiamo referenziare l’oggetto che rappresenta l’eccezione Cattura di un’eccezione I catch sono esaminati uno dopo l’altro nell’ordine in cui sono scritti “sovraccarico” dei catch Un blocco catch corrisponde all’oggetto lanciato se Sono dello stesso tipo (corrispondenza esatta) Il parametro è una classe base public dell’oggetto lanciato Il catch è il catch(…) Gli oggetti const lanciati corrispondono solo a parametri const Risollevare un’eccezione Quando un gestore di un’eccezione non è in grado di elaborarla, può rilanciare di nuovo l’eccezione throw senza argomenti un throw senza argomenti al di fuori di un blocco catch causa la terminazione immediata del programma Un’eccezione risollevata può essere ricatturata da un blocco try più esterno Flusso di controllo di un programma Se non si verifica alcuna eccezione, il codice del blocco try viene eseguito fino alla fine ed il contenuto del blocco catch è ignorato Se viene lanciata un’eccezione, l’esecuzione delle istruzioni nel blocco try termina e viene eseguita la procedura di gestione delle eccezioni Se esiste un blocco catch per gestire le eccezioni del tipo opportuno, viene eseguito Dopo l’esecuzione del blocco catch, l’esecuzione prosegue dall’istruzione che segue l’ultimo blocco catch Se non esiste nessun blocco catch in grado di gestire l’eccezione, l’esecuzione riprende dalla funzione terminate() (definita dalla libreria standard del C++ nell’header exception), che di default chiama abort per terminare l’esecuzione del programma Eccezioni della libreria standard Header exception Definisce exception, il tipo più generico di eccezione, indica solo il fatto che si è verificata un’eccezione Header stdexcept exception: il tipo più generale runtime_error: problema che può essere rilevato solo a runtime logic_errror: problema che avrebbe essere potuto rilevato prima dell’esecuzione domain_error: non esiste un risultato per questo valore dell’argomento invalid_argument: argomento di tipo non appropriato lenght_error: tentativo di crearo un oggetto di dimensione superiore alla massima consentita out_of_range Header new range_error: il risultano è fuori dal range overflow_error underflow_error Definisce bad_alloc, lanciata da new se non riesce ad allocare memoria Header type_info Definisce bad_cast Eccezioni della libreria standard Exception, bad_alloc, bad_cast hanno solo un costruttore di default Le eccezioni in stdexcept hanno solo un costruttore che prende una stringa di caratteri (messaggio di errore) Hanno solo il metodo const char* what() Restituisce un valore definito dal compilatore (per le eccezioni con costruttore di default) o la stringa passata come argomento al costruttore Specifica delle eccezioni Una funzione può specificare quali eccezioni può sollevare void int f(int a) throw (E1, E2); specifica che f() può sollevare solo eccezioni di tipo E1 e E2 Se f() dovesse sollevare un’eccezione di qualsiasi altro tipo, verrebbe trasformata in std::unexpected() Di default chiama std::terminate() che a sua volta invoca abort() int g() throw(); specifica che g() non solleverà alcuna eccezione double h(double x); può sollevare qualsiasi eccezione