Gestione delle eccezioni
In informatica la gestione delle eccezioni è un costrutto dei linguaggi di programmazione o un meccanismo dell'hardware del computer progettato per gestire errori a runtime o altri problemi (eccezioni) che avvengono durante l'esecuzione di un programma su un computer.
In generale, lo stato attuale verrà salvato in una posizione predefinita e l'esecuzione passerà a un gestore predefinito handler. A seconda della situazione, il gestore può poi riprendere l'esecuzione alla posizione originale, usando l'informazione salvata per ripristinare lo stato originale. Un esempio di eccezione da cui solitamente si riprende l'esecuzione è il page fault, mentre una che solitamente non può essere risolta trasparentemente è la divisione per zero.
Dal punto di vista dell'elaborazione, gli interrupt hardware sono simili a eccezioni recuperabili, eccetto che solitamente non sono correlate con il flusso attuale del programma.
Descrizione
modificaScopi delle eccezioni
modificaLa gestione delle eccezioni è rivolta a facilitare l'uso di meccanismi ragionevoli per gestire situazioni erronee o eccezionali che sorgono nei programmi. La gestione delle eccezioni può essere usata per passare informazioni sulle situazioni d'errore che avvengono all'interno di codice di libreria ai suoi utenti, e rispondere selettivamente a quegli errori.
Un possibile ruolo della gestione delle eccezioni è di permettere al programma di continuare la sua normale operatività e prevenire errori interni (crash), che comportano la visualizzazione di messaggi d'errore di difficile comprensione per l'utente. In molti casi, è sufficiente arrestare il programma e produrre un resoconto dell'errore; la differenza rispetto a sistemi che non fanno uso di eccezioni per segnalare esecuzioni anomale del programma sta nel fatto che con un'appropriata gestione delle eccezioni la condizione erronea può essere localizzata con precisione, semplificando il debugging.
La gestione delle eccezioni rende obsoleta la tecnica di gestione dei segnali presente in alcuni linguaggi.
Strutture di controllo
modificaLe eccezioni sono definite da linguaggi come C++, D, Java, C# e Python. La struttura di controllo utilizzata è il try-catch
: alcuni linguaggi supportano ulteriori clausole, come finally
o else
.
Esempi
modificaJava
modificaSi consideri questo semplice blocco di codice Java: si dichiara un array di interi di dimensione 5, e si prova ad accedere alla cella di memoria in una determinata posizione. Java genera un'eccezione se si prova ad accedere a tale porzione di memoria, se l'indice è maggiore o uguale della dimensione dell'array: questa eccezione può essere catturata in un blocco catch.
int posizione = ...;
try{
// dichiaro un array di interi di lunghezza 5
int array[]=new int[5];
// provo ad accedere alla posizione dell'array
// ma potrebbe essere maggiore della dimensione dell'array
array[posizione]=0;
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("Errore nell'accesso all'array");
}
Python
modifica
In Python è possibile gestire un'eccezione in un blocco try-except
. In questo esempio, il programma accetta una stringa in input e prova a convertirla in intero e termina dopo aver calcolato e stampato a schermo il doppio del numero inserito. Se la stringa inserita non può essere convertita, però, viene generata un'eccezione di tipo ValueError
. Il programma cattura questa eccezione ed esegue il codice all'interno del blocco except
, stampando un messaggio di errore. Nel blocco finally
, infine, si può scrivere del codice che viene eseguito al termine del blocco try-except
.
try:
intero = int(input("Inserisci un intero: "))
# l'esecuzione continua normalmente se non viene generata un'eccezione
doppio = intero * 2
print(f"Il doppio di {intero} è {doppio}.")
except ValueError:
print("Errore, non hai inserito un intero.")
finally:
print("Il programma è terminato.")
C++
modificaIn questo semplice esempio C++, il programma legge in input un intero, e stampa a schermo il risultato di una divisione nella quale il numero letto in input funge da denominatore. Se tale numero è 0, il programma stampa un messaggio di errore.
#include <iostream>
int main(){
int numeratore = 10;
int denominatore;
// leggo in input il valore del denominatore
std::cin >> denominatore;
try{
if (denominatore == 0){
// genero un'eccezione
throw 0;
}
// denominatore diverso da 0, stampo il risultato della divisione
std::cout << a/b << endl;
}
catch (int n) {
std::cout << "Denominatore zero." << std::endl;
}
return 0;
}
Bibliografia
modifica- Gian Carlo Macchi, Le condizioni eccezionali e la loro gestione, in Newsletter AICA "Affidabilità nei Sistemi di Elaborazione", n. 2, Scuola Superiore Guglielmo Reiss Romoli, maggio 1987. URL consultato il 25 novembre 2018.