Undantagshantering

Från Rilpedia

(Omdirigerad från Exception)
Hoppa till: navigering, sök
Wikipedia_letter_w.pngTexten från svenska WikipediaWikipedialogo_12pt.gif
rpsv.header.diskuteraikon2.gif

Undantagshantering (engelska exception handling) är namnet på mekanismer i programspråk eller datorhårdvara som är avsedda att hantera tillstånd där det normala programflödet behöver ändras. Dessa tillstånd kallas undantag (engelska exception), och orsakas av hårdvaran eller mjukvaran upptäcker ett undantagstillstånd som måste hanteras särskilt.

Varje processor har ett bestämt antal undantag som den kan utlösa. Exempel på vanliga hårdvaruundantag är sidfel eller division med noll. Mjukvaruundantag kan definieras av programmeraren själv och kan till exempel utlösas av övertrassering på ett konto, eller att mätvärdet från en termometer över- eller underskrider gränserna för det tillåtna temperaturintervallet.

I allmänhet avbryts processorn och dess tillstånd sparas på ett i förhand definierat ställe, varefter en undantagshanterare (engelska exception handler) tar över programflödet. Beroende på situationen kan hanteraren välja att återuppta kontrollflödet där det avbröts, genom att använda det sparade tillståndet. Till exempel återupptas flödet vid hanteringen av sidfel oftast utan att huvudprogrammet ens märker avbrottet. I andra fall, som till exempel nolldivision, finns det inget bra sätt att återuppta programflödet. Därför brukar undantagshanteraren vid nolldivision avsluta de felande programmet.

Hårdvaruundantag hanteras på liknande sätt som avbrott, med den väsentliga skillnaden att undantag alltid orsakas av något som det nuvarande programflödet har orsakat eller påträffat, medan avbrott alltid orsakas av externa fenomen (exempelvis signaler från hårddiskar eller tangentbordstryckningar) som inte har något att göra med det för tillfället exekverande programflödet.

Från ett programmerarperspektiv är mjukvaruundantag ett praktiskt sätt att signalera att en programprocedur inte kunde utföras på normalt vis, som när dess inparametrar är ogiltiga (exempelvis ogiltigt personnummer) eller när en resurs som proceduren behöver saknas (en datafil som saknas, eller diskenheten full). I system som saknar undantagshantering måste proceduren skicka en felkod till anropande procedurer. Detta komplicerar dock programkoden avsevärt och gör den betydligt mer svåröverskådlig.

Undantagshantering i programspråk

Många programspråk har inbyggt stöd för undantagshantering. I sådana språk orsakar ett undantag att stacken rullas upp tills en undantagshanterare hittas. Det vill säga om funktionen f, som har en hanterare H för undantag U, anropar funktionen g som i sin tur anropar h, och ett undantag av typen U inträffar i h, kommer h och g att avbrytas och H i f kommer att hantera U.

Med bortseende från mindre syntaktiska skillnader förekommer allmänt endast ett fåtal olika undantagshanteringstyper. I den mest populära typen utlöses ett undantag med en specifik programsats (throw, raise) med ett undantagsobjekt som beskriver undantaget. Den del av programmet som täcks av en undantagshanterare markeras med try eller liknande och avslutas med den första hanteringsklausulen som markeras med catch, except, rescue eller liknande. Flera hanteringsklausuler kan förekomma, var och ett specifierar då det undantag som hanteras.

Några språk har ytterligare en klausul (finally eller ensure) som exekveras oavsett om ett undantag inträffat eller inte, ofta för att frigöra resurser som används inom programblocket som undantagsskyddats.

Exempel

Ett exempel på hur felhanteringskod kan se ut följer (med C#-liknande syntax):

FileStream stm = null;
try {   // Här börjar undantagshanteringen.
    // Följande sats försöker öppnar en fil som kanske inte finns.
    stm = new FileStream("datafil.txt", FileMode.Open);  // **** 
    if (FilInnehållOgiltigt(stm))
        throw new InvalidFileContentsException("datafil.dat");
    // ... ytterligare programsater
 
} catch (InvalidFileContentsException ex) {
    Console.WriteLine("Innehållet i filen '" + ex.Filename + "' är ogiltigt.");
} catch (IOException ex) {
    // Undantagshantering för IO-fel som kanske uppstod vid raden
    // markerad med '****'
    Console.WriteLine("Ett fel uppstod vid bearbetningen av datafil.txt.");
} catch {
    Console.WriteLine("Ett okänt fel har inträffat.");
} finally {
    if (stm != null)     // städa upp eventuell öppen fil.
        stm.Close();
}
Personliga verktyg