• No results found

Felhantering - Exceptions. Reaktion vid feltillstånd. Reaktion vid feltillstånd När, var och hur.

N/A
N/A
Protected

Academic year: 2022

Share "Felhantering - Exceptions. Reaktion vid feltillstånd. Reaktion vid feltillstånd När, var och hur."

Copied!
7
0
0

Loading.... (view fulltext now)

Full text

(1)

Karlstads universitet Datavetenskap

Avancerad C++, DAVC05

Felhantering - Exceptions

När, var och hur.

Felhantering - Exceptions, Sida 2 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Vad ska en operation göra när den upptäcker att minnet är fullt eller när den tvingas göra det omöjliga, exempelvis poppa från en tom stack?

Reaktion vid feltillstånd

Reaktion vid feltillstånd

• Strategier

– Returnera en felkod

Att returnera en felkod kan vara bra speciellt i funktioner, som förr eller senare inte kommer att kunna utföra det normala beteendet.

En del av kontrakten för funktionen.

– Sätta en felflagga

C’s lösning på att rapportera fel som inte kan härledas från ett kontraktsbrott.

Fungerar dåligt vid nästlade uttryck.

Employee readEmployee(istream&);

Bool

readEmployee(istream&,E mployee&);

double sqrt(double x ) {

if(x<0){

erno = EDOM;

return 0;

} }

…..

erno = 0;

Y = sqrt(x);

If(errno != 0)

…..

(2)

Felhantering - Exceptions, Sida 4 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Reaktion vid feltillstånd (forts)

– Skriva ut ett felmeddelande

Att rapportera ett felmeddelande är ok i studentprogram och vid debuggning. Användare av den slutgiltiga produkten ska definitivt inte få upp några felmeddelande, som de varken förstår eller kan hantera.

Detta är dock ingen lösning på det övergripande problemet.

– Avsluta programmet

I enkla program kan det vara acceptabelt att först skriva ut ett felmeddelande och sedan avsluta programmet. Återigen är detta inte acceptabelt för den slutgiltiga produkten, ty användaren riskera att förlora data.

Detta är dock heller inte någon lösning på det övergripande problemet.

Felhantering - Exceptions, Sida 5 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Reaktion vid feltillstånd (forts)

– Hoppa till en felhanterare

Det kan ofta vara svårt att hantera ett fel där det händer, exempelvis har en konstruktor svårt att hantera externa fel, som att minnet har tagit slut.

Felhanteringen måste göras på annat håll, i en s.k. felhanterare.

C-program kan använda sig av setjmp och longjmp för att hoppa till en felhanterare, men dessa kommandon är ej kompatibla med C++.

– Kasta ett undantag

C++ har en mekanism för att kasta undantag när fel upptäcks. Denna mekanism styr om programflödet, enligt programmeraren instruktioner, så att felinformation hamnar hos en felhanterare som hanterar just detta fel.

Denna Felhantering är dynamiskt, d.v.s. exakt vilken det blir är inte känt före körning.

Användning av undantag

• Om ett fel uppstår, som inte kan hanteras lokalt där felet uppstod, kan ett undantag kastas.

• Externa fel (Kan oftast ej förutses) – Resursbegränsningar, ex. slut på minne.

– Fel som uppstår vi kommunikation över internet, ex. broken pipe.

– Fel som uppstår vi interaktion med Externa apparater.

– …… I allmänhet fel som inte uppstår i det normala programflödet och som inte kan förutses och förhindras med förvillkor.

• Interna fel (Förutsägbara)

Inga fel som uppstår i det normala programflödet ska hanteras med exceptions.

För- och eftervillkor är default mekanismen.

(3)

Felhantering - Exceptions, Sida 7 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Användning av undantag(forts)

• Martin Fowler, UML Distilled, Third Edition, sid 51:

"An exception occurs when an operation is invoked with its pre-condition satisfied yet cannot return with its post-condition satisfied.“

• Utforma för och eftervillkor som om att externa fel inte uppstår. Lägg sedan till undantag sist med dess beskrivning.

Felhantering - Exceptions, Sida 8 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

När kastar C++ undantag

• operatorn new(size_T);

– Kompilator beroende

• Kastar bad_alloc om den inte får tag i det minnet den behöver.

eller

• Kastar inget undantag men returnerar ”0” om den inte får tag i något minne.

Syntax - Exceptions

• throw

– Undantag kastas m.h.a. operationen throw

– Objekt som kastas bör innehålla information om undantaget.

– Typen på objektet som kastas är valfri. Pekare till objekt är tillåtna men bör dock inte användas.

• try-catch block

– Den kod som anropar en funktion som kan kasta ett undantag och vill hantera undantaget, ska lägga anropet i ett try-catch block.

– Det är ett fritt val för programmeraren att hantera eller ignorera undantag som kastas.

Void func(){

throw Exception(”Error”);

}

try{

func(); // trows exceptions }catch(…){

}

(4)

Felhantering - Exceptions, Sida 10 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Vid throw anropet

• Ett objekt skapas som inte existerar under den normala exekveringen.

• Funktionen där undantaget kastades kommer att avslutas i förtid.

– Kontrollen kommer att flyttas till den första felhanterare, som kan hantera det aktuella undantaget.

– Eventuella funktioner kommer att avslutas, dock inte returnera. Alla funktionslokala objekt kommer dock att avallokeras.

Gäller alla funktioner som ligger mellan felhanteraren och där undantaget kastades.

Vad händer med de objekt som är skapade på heapen och är bara utpekade av en pekare?

– Kontrollen återgår aldrig till den funktion som kastade undantaget.

• Objektet kastas ut från det funktionsblock som kastade det.

– ”Ersätter” det vanliga returvärdet.

Run-Time stacken

main() func() throwningFunc()

catchingFunc()

Felhantering - Exceptions, Sida 11 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Det kastade objektet

• Typen på det kastade objektet är valfritt.

• C++ har i <stdexcept> definierat ett antal undantag nedan.

– Notera att användningen av vissa inte är lämpligt i kombination med kontraktsprogrammering.

– Egna hierarkier kan skapas

• Hierarkier av undantag uppmuntras – Underlättar hantering

– Ett gemensamt interface

ex ception

logic_error bad_al loc bad_cast run time_e rror

invalid_argument out_of_range domain_error length_error

range_error un derfl ow_ error

Felhanteraren – catch-blocket

catch-blocket som följer efter eventuell try sats är vår undantagshanterare.

För att fånga ett undantag krävs ett try-block

Ett try-block kan följas av en mängd felhanterare.

En felhanterare definierar på den första raden vilken typ av fel den vill hantera.

Kompilatorn letar uppifrån och ner efter en lämplig felhanterare.

Ett undantag kan fångas som referens eller värde

Referens möjliggör att härledda undantag kan fångas. (Polymorfism, Se sida 9) Typen på undantaget kan lämnas odefinierat och

ersättas med (…), som implicerar att felhanteraren hanterar alla undantag.

Nackdelen är att undantagsobjekten inte går att läsa av, bara kastas vidare.

Möjliggör en generell hantering vid svåra situationer.

Bör placeras sist, då den alltid matchar ett undantag.

try{

func1(); // throws Exception1 func2(); // throws Exception2 }

catch(Exception1 e){

//Felhanteringskod }

catch(Exception2& e){

//Felhanteringskod }

catch(…){

//Felhanteringskod }

(5)

Felhantering - Exceptions, Sida 13 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Tips

• Fånga alltid undantag om du behöver avallokera objekt innan funktionen tas bort.

• Skicka vidare undantaget om ett utanpåliggande block kan hantera situationen bättre.

• Hantera undantagen! Ditt program kommer att abrupt avsluta om du missar att fånga ett.

Felhantering - Exceptions, Sida 14 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Beteende hos en felhanterare

• I allmänhet ska en felhanterare endast ta emot de fel den kan hantera.

• Exempel på hur undantag kan hanteras:

1. Kör den felande operationen på nytt efter att eventuella åtgärder har utförts.

2. Städa undan rester från den felande operationen och skicka sedan ett nytt eller samma undantag vidare till en annan hanterare.

3. Gör ingenting och skicka vidare undantaget

bool success = false;

while(success == false){

try{

func1(); // throws success = true;

}catch(Exception e){

Prepair retry;

} }

Type ptr = new Type;

try{

func1(); // throws }catch(Exception e){

delete ptr; //clean up;

throw; // eller throw e }

try{

func1(); // throws }catch(Exception1 e){

throw; //

}

Undantagsspecifikation

• Användare av en funktion, som kastar undantag, måste bli informerad av att undantag kan komma att kastas.

– Det är i dagsläget beroende på kompilatorn.

• GNU (gcc, g++, etc)

• Visual C++ 6

– Om specifikationen saknas får alla möjliga undantagsobjekt kastas – En tom specifikationen betyder att inga

undantag kommer att kastas.

• Kontrolleras inte av kompilatorn men hanteras av funktionen unexpected.

// pre: True // post: pop() == data template<class T>

void push(T data) throw(bad_alloc);

// pre: True // post: pop() == data // Exceptions: bad_alloc template<class T>

void push(T data);

(6)

Felhantering - Exceptions, Sida 16 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Pre och Post med undantag

• Skulle man mot förmodan välja att använda undantag för interna fel, brutna för-villkor, måste även undantag inkluderas i för- och efter-villkor.

// pre: True

// post: if 0 < index < getSize() // objekt at index is returned // else

// Exception range_error is thrown template<class T>

T& operator[](const int index) throw(range_error);

Felhantering - Exceptions, Sida 17 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Potentiella minnesläckor

• Objekt allokerade på heapen måste frigöras explicit.

• auto_ptr är ett generellt sätt att hantera heap allokerade objekt;

– En template klass – Innehåller en variant av

referensräknare – Frigör det allokerade

minnet när alla referenser till heap-objektet är borta.

try{

int *array = new int[10];

throw ”something”;

}catch(…){

}

try{

auto_ptr<int*> array = new int[10];

throw ”something”;

}catch(…){

//delete[] array; behövs ej // auto_ptr tar bort //objektet åt oss }

int* array;

try{

array = new int[10];

throw ”something”;

}catch(…){

delete[] array;

}

Konstruktorer och destruktorer

• Destruktorer

– Det rekommenderas att undantag inte kastas av destruktorer. Om en destruktor kastar ett undantag så kommer programmet att terminera.

• Konstruktorer(Ett knepigt kapitel med många svårigheter)

– Kompilator beroende

• GNU anropar inte destruktorn på det skapade/missbildade objektet.

• GNU anropar dock destruktorn för klassens medlemmar.

– Auto_ptr<T> är ett lämpligt alternativ till vanliga pekare.

– Innan undantaget kastas bör konstruktorn ta hand om så mycket minne den kan.

– ”destroyable state” ska gälla för objektet innan undantaget kastas.

Class A;

Class Error;

A::A(int size){

reserved = new char[size];

//…

if(some error) throw Error(”O-no”);

//BAD, leave allocated //memory block reserved }

Class A;

Class Error;

A::A(int size){

reserved = new char[size];

if(some error) delete[] reserved;

throw Error(”O-no”);

//OK, leave allocated //memory block reserved }

(7)

Felhantering - Exceptions, Sida 19 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Invarianter och undantag

• Om undantag kastas i en konstruktor – Inte så viktigt att invarianter är uppfyllda.

– Det objektet som är på väg att skapas kommer inte att finnas efter att undantaget är kastat.

• Inte ens objektets destruktor kommer att anropas

• Om undantag kastas i ex. operator=(…)

– Objektet kommer att fortsätta att existera trots att ett undantag kastas.

– Mycket viktigt att objektets invarianter är uppfyllda innan operatorn kastar undantag.

Felhantering - Exceptions, Sida 20 Avancerad C++, DAVC05 Karlstads universitet

Datavetenskap

Undantag för undantagen

• unexpected()

– Anropas om undantagsspecifikation inte innehåller den typ som det kastade objektet är av.

– Denna funktion existerar inte per default.

• Istället anropas terminate(), se nedan.

– std::set_unexpected( myFunc ) pekar ut en egendefinierad unexpected().

• Namnet på den egna funktionen är inte signifikant.

• terminate() – Anropas om:

1. Ett undantaget fångades aldrig.

2. Run-Time stacken har blivit korrumperad efter att undantaget kastades.

3. Om unexpected anropas då set_unexpected inte har anropas.

4. Om en destruktorn försöker kasta ett undantag.

– std::set_terminate( myFunc ) kan användas för att använda en egen

”terminate” funktion.

References

Related documents

De positiva signifikanta resultaten för CAR under perioden 1985-2005 visar tydliga tecken på att blockförvärv i genomsnitt fungerar som en värdegenererande faktor för

Definierar regler hur felet ska skickas vidare, T.ex. skickas felet med saknad marknad till system som automatisk kan ge produkten en marknad beroende på parametrar som.. För

Identifierade t-värden från testerna för respektive handelsplats uppvisar samtliga signifikanta resultat på en femprocentig nivå, vilket innebär att AVOL förekommer på Small Cap,

Uttalanden från dessa följde dock inte proportionellt antal experter eftersom tabellen visar att antal uttalanden från experter inom svenska myndigheter var nästan 4 gånger

Anledningen till att undersökningen börjar år 1996 är att den svenska elmarknaden avreglerades vid årsskiftet 1995/96 och data från de föregående åren skulle kunna bidra

Det finns anledning till att undersöka vilken betydelse etiskt ledarskap har för revisionsbyråers felsökningsklimat på grund av att den tidigare forskningen inte

Om emancipation och sedlighet Om modernitet och den nya kvinnan NORMER, ESTETIK OCH KANON Människosyn och kärleksbegrepp?. KVINNOR I RÖRELSE MOT DUBBELMORALEN EN

Istället för att anta erbjudandet om att ansluta sig till Ellen Keys Eroslära sökte många kvinnor en mening med sitt liv i en kristen tro, kvinnlig vänskap eller arbete. Många