För fastighetsrätten, se undantag (fastighetsrätt).

Undantagshantering (engelska: exception handling) är mekanismer i programspråk eller datorhårdvara som ändrar det normala programflödet för att hantera undantag (engelska: exception). Vid ett undantag sparas processorns exekveringstillstånd och programflödet omdirigeras till en undantagshanterare (engelska: exception handler).

Beroende på situationen kan undantagshanteraren välja att återuppta programflödet där det avbröts, genom att använda det sparade exekveringstillståndet. Exempelvis återupptas programflödet efter sidfel utan problem. Vid oväntad division med noll finns det däremot inget självklart sätt att återuppta programflödet, eftersom beräkningen som försökte göras sannolikt skulle bli felaktig om man försökte fortsätta. Därför brukar undantagshanteraren vid sådana undantag avsluta det felande programmet, åtminstone under utvecklingsprocessen (och registrera på vilken programrad undantaget skedde) eftersom undantaget kan bero på en bugg, och återstarta på ett lämpligt sätt i kundprogramvara.

Undantagstyper

redigera

Mjukvaruundantag definieras i ett programs programkod som ett alternativ till felkoder, medan hårdvaruundantag hör till en viss processor.

Mjukvaruundantag

redigera

Från ett programmerarperspektiv är mjukvaruundantag ett sätt att signalera att en programprocedur inte kunde utföras på normalt vis, vilket till exempel kan ske när inparametrar är ogiltiga (exempelvis ogiltiga personnummer) eller när en resurs som proceduren behöver saknas (en datafil som saknas, eller att diskenheten är full). I system som saknar undantagshantering måste proceduren skicka en felkod till anropande procedurer, vilket kan göra programkoden svåröverskådlig.

Hårdvaruundantag

redigera

Exempel på hårdvaruundantag är: sidfel och division med noll. Hårdvaruundantag är besläktade med avbrott, med skillnaden att hårdvaruundantag orsakas av programfel, medan avbrott orsakas av externa händelser (exempelvis signaler från hårddisk eller tangentbord).

Undantagshantering i programspråk

redigera

En del 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 och var och en specificerar 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

redigera

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

FileStream stm = null;
try {// Här börjar undantagshanteringen.
    stm = new FileStream("datafil.txt", FileMode.Open);  // Öppna en fil som kanske inte finns.
    if (FilInnehållOgiltigt(stm))
        throw new InvalidFileContentsException("datafil.dat"); // Undantag skapas.
    
} catch (InvalidFileContentsException ex) { // Undantagshantering för det skapade undantaget.
    Console.WriteLine("Innehållet i filen '" + ex.Filename + "' är ogiltigt.");
} catch (IOException ex) { // Undantagshantering för IO-fel som kanske uppstod när filen öppnades.
    Console.WriteLine("Ett fel uppstod vid bearbetningen av datafil.txt.");
} catch { // Undantagshantering för generella undantag.
    Console.WriteLine("Ett okänt fel har inträffat.");
} finally {
    if (stm != null)
        stm.Close(); // Städa upp eventuell öppen fil.
}