Exception handling
Exception handling is een constructie of een mechanisme die een programmeertaal biedt om op een abnormale of uitzonderlijke gebeurtenis (excepties) te kunnen reageren en af te handelen tijdens het uitvoeren (run time) van software. De normale afloop van het programma wordt gewijzigd in tijdelijke onderbreking of een totale afbreking. Als er geen aandacht in het programma aan de mogelijke exceptie is besteed, meldt het systeem een "unexpected exception", meestal gevolgd door een rapportage.
Voorbeelden van excepties
bewerkenExcepties kunnen optreden bij onder meer:
- lees- of schrijffouten met input/output periferie;
- bij schrijven naar of lezen uit geheugen dat niet voor het programma is bestemd;
- bij delen door nul;
- een of andere overflow;
- door de softwareontwikkelaar bedachte excepties.
Veel programmeertalen geven de programmeur de mogelijkheid om eigen excepties te definiëren.
De meest voorbeeldige exceptie is de rekenkundige deling door het getal 0. Het is bijna ondoenlijk om in het programma bij elke deling de deler te controleren op de waarde 0. En het aantal malen dat de programmeur dit zou moeten doen, staat in geen verhouding tot het geringe aantal keren dat dit feitelijk gebeurt. Daarom biedt het exceptiemechanisme een mogelijkheid om deze fout centraler af te handelen, meestal zodanig dat de verwerking minimaal wordt gestoord.
Doel van de excepties
bewerkenExcepties zijn bedoeld om de programmeur een praktisch mechanisme te geven om fout- en uitzonderingssituaties af te vangen die in software kunnen voorkomen. Zo kunnen op een hoger niveau fouten worden afgevangen die op een lager niveau worden veroorzaakt, zonder dat in enig tussenliggend niveau hier speciale code voor hoeft te worden toegevoegd.
Werking
bewerkenDe sleutel van de exceptieconstructie in een programmeertaal is het groeperen van statements in blokken, zoals ingevoerd is bij het gestructureerd programmeren. Een code-blok wordt aangemerkt dat het een exceptie kan verwerken en bovendien wordt het uitgebreid met een gedeelte die de exceptie verwerkt, de zogenaamde exception-handler. Blokken kunnen genest zijn en daarom hoeft het (binnenste) blok waar de exceptie ontstaat niet een handler te hebben. Zolang de exceptie niet behandeld is, zoekt het mechanisme van binnen naar buiten naar het blok wat het vorige blok heeft aangeroepen op een toepasselijke handler. Ondertussen is de verdere uitvoering in de blokken waar geen passende handler is gevonden, geforceerd afgebroken en zijn de variabelen verloren. Uiteindelijk vindt het mechanisme een blok met een handler en wordt de code in het handlergedeelte uitgevoerd. Het vinden van een handler is gegarandeerd, omdat het systeem wat het programma start als het ware het buitenste omhullend blok is, met algemene handlers. Deze "unexpected exception" handlers zijn echter niet voor een eindgebruiker bedoeld en breken het programma in zijn geheel af.
Exceptie-robuustheid
bewerkenEen stuk software wordt exceptieveilig (exception-safe) genoemd als runtimefouten binnen de code niet leiden tot geheugenlekken, corrupte data of onjuiste uitvoer. Er zijn een aantal niveaus van exceptieveiligheid:
- Fout-transparant (best): alle stappen van het programma slagen altijd en voldoen aan alle eisen, zelfs in aanwezigheid van uitzonderlijke situaties;
- Vastleg- of terugdraaitechniek: enkele stappen van het programma kunnen ontbreken, maar de ontbrekende stappen hebben geen neveneffecten;
- Basis exceptieveiligheid: de ontbrekende stappen kunnen bijwerkingen veroorzaken, maar de juiste toestand wordt bewaard (dus alle opgeslagen informatie is correct);
- Minimale exceptieveiligheid: gedeeltelijke uitvoering van het programma kan onjuiste data opleveren, maar zal geen crash veroorzaken;
- Geen exceptieveiligheid (slechtst): het programma heeft geen passende afhandeling en crasht met gebruikersonvriendelijke systeemmeldingen.
Normaal is een basis exceptieveiligheid vereist. Fout-transparantie is moeilijk, zo niet onmogelijk te implementeren.
Exceptie-ondersteuning in programmeertalen
bewerkenVele programmeertalen, die blokgestructureerd zijn, zoals onder meer Ada, C#, C++, Common Lisp, D, Delphi, Eiffel, Java, Objective-C, PHP, PL/SQL, Python, Scala, hebben ondersteuning voor excepties en exception handling. In deze talen wordt bij het optreden van een exceptie de stack van functieaanroepen afgewikkeld totdat een exception handler voor deze exceptie is gevonden.
try
{
// Code die een exceptie kan opleveren
}
catch(e:Error)
{
//Verwerk een systeemexceptie.
}
finally
{
// (optioneel) code die altijd uitgevoerd wordt
}
public static void Main()
{
try {
// Code die een exceptie kan opleveren
} catch(System.Exception) {
//Verwerk een systeemexceptie.
} catch {
//Verwerk een andere exceptie.
} finally {
// (optioneel) code die altijd uitgevoerd wordt
}
}
#include <exception>
int main() {
try {
// Code die een exceptie kan opleveren
}
catch (const std::exception& e) {
//Verwerk een standaardexceptie.
}
catch (...) {
// onbekende exceptie
}
}
try
try
// Code die een exceptie kan opleveren
finally
// Code die uitgevoerd zal worden ongeacht of er een exceptie opgetreden is
end;
except
on E:Exception do
//Verwerk een Exceptie
end;
try {
// Code die een exceptie kan opleveren
} catch (VoorbeeldExceptie ee) {
//Verwerk een voorbeeldexceptie
} catch (Exception b) {
// Verwerk de overige excepties
} finally {
// (optioneel) code die altijd uitgevoerd wordt
}
try {
// Code die een exceptie kan opleveren
} catch (ExceptieClass $exceptie) {
//Verwerk een ExceptieClass exceptie
}
try:
//Code die een exceptie op kan leveren
except exceptie1:
//Code die uitgevoerd moet worden wanneer exceptie1 optreedt
//optioneel:
except exceptie2:
//Code die uitgevoerd moet worden wanneer exceptie2 optreedt
else:
//Code die uitgevoerd moet worden wanneer geen van de vorige excepties zijn opgetreden
finally:
//Code die altijd uitgevoerd moet worden ongeacht of er een exceptie is opgetreden
TRY
// Code die een exceptie kan opleveren
CATCH (n_exc_myexception le_myexception) {
//Verwerk de exceptie van type n_exc_myexception
CATCH (exception le_exception) {
//Verwerk de overige excepties
FINALLY
// (optioneel) code die altijd uitgevoerd wordt vóór de code na het END TRY statement
END TRY