Difference between revisions of "Exceptions/fi"
Line 3: | Line 3: | ||
=Poikkeukset= | =Poikkeukset= | ||
− | Free Pascal tukee poikkeuksia. Poikkeukset ovat hyödyllisiä virheiden käsittelyssä ja resurssien vuotojen välttämisessä. Muista kuitenkin, että poikkeuksilla on suorituskykyvaikutusta. | + | [[FPC/fi|Free Pascal]] tukee poikkeuksia. Poikkeukset ovat hyödyllisiä virheiden käsittelyssä ja resurssien vuotojen välttämisessä. Muista kuitenkin, että poikkeuksilla on suorituskykyvaikutusta. |
Virallinen dokumentaatio löytyy täältä: [https://www.freepascal.org/docs-html/ref/refch17.html]. | Virallinen dokumentaatio löytyy täältä: [https://www.freepascal.org/docs-html/ref/refch17.html]. | ||
− | Oletuksena poikkeukset on pois käytöstä. Se voidaan valita käyttöön kun käytetään [[Mode_ObjFPC|ObjFPC]] tai [[Mode_Delphi|DELPHI]] [[Compiler Mode|kääntäjän moodia]] | + | Oletuksena poikkeukset on pois käytöstä. Se voidaan valita käyttöön kun käytetään [[Mode_ObjFPC|ObjFPC]] tai [[Mode_Delphi|DELPHI]] [[Compiler Mode/fi|kääntäjän moodia]] |
− | tai lisäämällä parametrin -Sx kääntäjän komentoriville. Tämä mahdollistaa [[Try/fi|< | + | tai lisäämällä parametrin -Sx [[Compiler/fi|kääntäjän]] [[Command-line interface/fi|komentoriville]]. Tämä mahdollistaa [[Try/fi|<syntaxhighlight lang="pascal" enclose="none">try</syntaxhighlight>]], [[Raise/fi|<syntaxhighlight lang="pascal" enclose="none">raise</syntaxhighlight>]], [[Except/fi|<syntaxhighlight lang="pascal" enclose="none">except</syntaxhighlight>]] ja [[Finally/fi|<syntaxhighlight lang="pascal" enclose="none">finally</syntaxhighlight>]] [[Reserved word/fi|varatut sanat]] käytettäväksi omassa koodissasi, mutta se ei salli poikkeuksia [[RTL/fi|RTL]]:stä. Jotta RTL voi nostaa poikkeuksia sen sijaan, että se tuottaa [[runtime error/fi|ajonaikaisia virheitä]], käytä ohjelman SysUtils-käännösyksikköä. |
− | Poikkeusten kantaluokka < | + | Poikkeusten kantaluokka <syntaxhighlight lang="pascal" enclose="none">Exception</syntaxhighlight> löytyy SysUtils [https://www.freepascal.org/docs-html/rtl/sysutils/exception.html] käännösyksiköstä. Kaikissa poikkeuksissa tulisi käyttää tätä [[Class/fi|luokkaa]] tai jotain siitä johdettua luokkaa. |
== Esimerkit == | == Esimerkit == | ||
− | Huomaa, että Pascal käyttää eri [[Keyword|avainsanoja]] kuin jotkut muut kielet: < | + | Huomaa, että [[Pascal/fi|Pascal]] käyttää eri [[Keyword|avainsanoja]] kuin jotkut muut kielet: <syntaxhighlight lang="pascal" enclose="none">raise</syntaxhighlight> vastaa <syntaxhighlight lang="pascal" enclose="none">throw</syntaxhighlight>:ta ja <syntaxhighlight lang="pascal" enclose="none">except</syntaxhighlight> vastaa <syntaxhighlight lang="pascal" enclose="none">catch</syntaxhighlight>:a. |
− | Myös kääntäjä on suunniteltu niin että valinnan mukaan kukin < | + | Myös kääntäjä on suunniteltu niin että valinnan mukaan kukin <syntaxhighlight lang="pascal" enclose="none">try</syntaxhighlight>-lohko voidaan yhdistää joko <syntaxhighlight lang="pascal" enclose="none">except</syntaxhighlight> tai <syntaxhighlight lang="pascal" enclose="none">finally</syntaxhighlight>-lohkoon, mutta ei molempiin samanaikaisesti. Jos tarvitaan sekä <syntaxhighlight lang="pascal" enclose="none">except</syntaxhighlight> että <syntaxhighlight lang="pascal" enclose="none">finally</syntaxhighlight>-lohkoa suojaamaan samaa koodia niin ne laitetaan sisäkkäin. |
=== Virheiden käsittely === | === Virheiden käsittely === | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="pascal"> |
try | try | ||
// Tee jotain, joka saattaa mennä pieleen. | // Tee jotain, joka saattaa mennä pieleen. | ||
Line 32: | Line 32: | ||
=== Resurssien siivoaminen === | === Resurssien siivoaminen === | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="pascal"> |
try | try | ||
// Tee jotain, joka saattaa mennä pieleen. | // Tee jotain, joka saattaa mennä pieleen. | ||
Line 42: | Line 42: | ||
=== Poikkeuksen nostaminen === | === Poikkeuksen nostaminen === | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="pascal"> |
raise Exception.Create('Jokin hyödyllinen kuvaus siitä, mikä meni pieleen'); | raise Exception.Create('Jokin hyödyllinen kuvaus siitä, mikä meni pieleen'); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 48: | Line 48: | ||
=== Käytä omia erikoistuneita poikkeustyyppejä eri ongelmien ilmoittamiseen === | === Käytä omia erikoistuneita poikkeustyyppejä eri ongelmien ilmoittamiseen === | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="pascal"> |
type EMyLittleException = Class(Exception); | type EMyLittleException = Class(Exception); | ||
Line 76: | Line 76: | ||
* Mutta nostetaan poikkeus, jos on kriittinen virhe havaitaan; ohjelmoijat voivat unohtaa tarkistaa palautetut virhearvot. | * Mutta nostetaan poikkeus, jos on kriittinen virhe havaitaan; ohjelmoijat voivat unohtaa tarkistaa palautetut virhearvot. | ||
* Nimeämiskäytäntö: Etuliite poikkeusluokan nimillä, joka on iso E-kirjain. | * Nimeämiskäytäntö: Etuliite poikkeusluokan nimillä, joka on iso E-kirjain. | ||
− | * Uudelleen nostetaan poikkeus < | + | * Uudelleen nostetaan poikkeus <syntaxhighlight lang="pascal" enclose="none">except</syntaxhighlight> -lohkossa käyttämällä <syntaxhighlight lang="pascal" enclose="none">raise</syntaxhighlight> käskyä jos ei kyetä toipumaan ongelmasta; tämä säilyttää alkuperäisen poikkeuksen callstackin. |
− | * Pitää olla varovainen, kun käytetään catch-all < | + | * Pitää olla varovainen, kun käytetään catch-all <syntaxhighlight lang="pascal" enclose="none">Exception</syntaxhighlight> luokkaa, koska alla oleva koodi, käyttöjärjestelmä tai tiedostojärjestelmä saattaa tuottaa odottamattoman poikkeuksen, joka saattaa mennä tällöin poikkeustilanteesta läpi, mikä voi mahdollisesti pilata ohjelman suorituksen. |
* Pidetään poikkeusten käsittely pois koodista, joka on suoritettava mahdollisimman nopeasti. | * Pidetään poikkeusten käsittely pois koodista, joka on suoritettava mahdollisimman nopeasti. | ||
Line 88: | Line 88: | ||
Jotta saadaan parempi tuntuma, mitä tapahtuu, kokeile pienen testiohjelman kirjoittamista ja kääntämistä -a -kytkimellä. Tämä tekee ihmisen luettavissa olevan assemblytiedosto. | Jotta saadaan parempi tuntuma, mitä tapahtuu, kokeile pienen testiohjelman kirjoittamista ja kääntämistä -a -kytkimellä. Tämä tekee ihmisen luettavissa olevan assemblytiedosto. | ||
− | * < | + | * <syntaxhighlight lang="pascal" enclose="none">Try</syntaxhighlight>-lauseessa lisätään ylimääräisiä osoitteen laskemista, pinoon laittoa (push) ja siitä poistoa (pop), joitakia suoria hyppykäskyjä ja ehdollisen hypyn. |
− | * < | + | * <syntaxhighlight lang="pascal" enclose="none">Except</syntaxhighlight>-lause lisää yllä olevan pinoon laittoa (push) ja siitä poistoa (pop), enemmän suoria hyppykäskyjä ja toisen ehdollisen hypyn. |
− | * < | + | * <syntaxhighlight lang="pascal" enclose="none">Finally</syntaxhighlight>-lause lisää pinosta poiston (pop) ja ehdollisen hyppyn, jotta poikkeus voidaan nostaa uudelleen. |
− | * < | + | * <syntaxhighlight lang="pascal" enclose="none">Raise</syntaxhighlight>-lause luovat merkkijonon ja ohittaa FPC:n hallinnan poikkeuksen noston. |
− | * < | + | * <syntaxhighlight lang="pascal" enclose="none">Raise</syntaxhighlight>-lause luovat myös poikkeuskehyksen kyseiselle funktiolle / -menetelmälle, vaikka Raise-lausetta ei toteuttettaisi. Siksi esim. säiliötyypeissä näkee usein, että raise-komento siirretään erilliseen paikalliseen (yksityiseen) aliohjelmaan. Tällöin aliohjelmalla on poikkeuskehys, mutta vain silloin, kun se toteutetaan. |
− | Lisäksi, jos halutaan ihmisen luettavissa olevan callstack:n virheenjäljityksen apuna niin käytetään SysUtils käännösyksikön funktioita < | + | Lisäksi, jos halutaan ihmisen luettavissa olevan callstack:n virheenjäljityksen apuna niin käytetään SysUtils käännösyksikön funktioita <syntaxhighlight lang="pascal" enclose="none">ExceptAddr</syntaxhighlight>, <syntaxhighlight lang="pascal" enclose="none">ExceptFrames</syntaxhighlight>, <syntaxhighlight lang="pascal" enclose="none">ExceptFrameCount</syntaxhighlight> ja <syntaxhighlight lang="pascal" enclose="none">BackTraceStrFunc</syntaxhighlight>, tosin se vaatii aikaa vievää pinoon siirtämistä ja merkkijonojen käsittelyä. |
Kuten sanottiin, että raskas koodin käsittely kyseisen kohdan ulkopuolella poikkeuksella yleensä ylittää niiden suorituskykyvaikutukset. Ei pidä tuntea pahaa siitä, että pystyy kirjoittamaan parempaa ohjelmakoodia. | Kuten sanottiin, että raskas koodin käsittely kyseisen kohdan ulkopuolella poikkeuksella yleensä ylittää niiden suorituskykyvaikutukset. Ei pidä tuntea pahaa siitä, että pystyy kirjoittamaan parempaa ohjelmakoodia. |
Revision as of 21:30, 5 July 2019
│
English (en) │
suomi (fi) │
Poikkeukset
Free Pascal tukee poikkeuksia. Poikkeukset ovat hyödyllisiä virheiden käsittelyssä ja resurssien vuotojen välttämisessä. Muista kuitenkin, että poikkeuksilla on suorituskykyvaikutusta.
Virallinen dokumentaatio löytyy täältä: [1].
Oletuksena poikkeukset on pois käytöstä. Se voidaan valita käyttöön kun käytetään ObjFPC tai DELPHI kääntäjän moodia
tai lisäämällä parametrin -Sx kääntäjän komentoriville. Tämä mahdollistaa try
, raise
, except
ja finally
varatut sanat käytettäväksi omassa koodissasi, mutta se ei salli poikkeuksia RTL:stä. Jotta RTL voi nostaa poikkeuksia sen sijaan, että se tuottaa ajonaikaisia virheitä, käytä ohjelman SysUtils-käännösyksikköä.
Poikkeusten kantaluokka Exception
löytyy SysUtils [2] käännösyksiköstä. Kaikissa poikkeuksissa tulisi käyttää tätä luokkaa tai jotain siitä johdettua luokkaa.
Esimerkit
Huomaa, että Pascal käyttää eri avainsanoja kuin jotkut muut kielet: raise
vastaa throw
:ta ja except
vastaa catch
:a.
Myös kääntäjä on suunniteltu niin että valinnan mukaan kukin try
-lohko voidaan yhdistää joko except
tai finally
-lohkoon, mutta ei molempiin samanaikaisesti. Jos tarvitaan sekä except
että finally
-lohkoa suojaamaan samaa koodia niin ne laitetaan sisäkkäin.
Virheiden käsittely
try
// Tee jotain, joka saattaa mennä pieleen.
except
on E : Exception do begin
// Yritä palauttaa tai näytä käyttäjälle virheilmoitus
end;
end;
Resurssien siivoaminen
try
// Tee jotain, joka saattaa mennä pieleen.
finally
// Siivoa resurssi lopuksi (kutsutaan aina, myös poikkeus tilanteissakin).
end;
Poikkeuksen nostaminen
raise Exception.Create('Jokin hyödyllinen kuvaus siitä, mikä meni pieleen');
Käytä omia erikoistuneita poikkeustyyppejä eri ongelmien ilmoittamiseen
type EMyLittleException = Class(Exception);
begin
try
raise EMyLittleException.Create('Foo');
except
on E : EMyLittleException do writeln(E.Message);
on E : Exception do writeln('This is not my exception!');
end;
end;
Poikkeusluokat
Käännösyksikkö SysUtils määrittelee ja nostaa monia erityisiä poikkeusluokkia: [3]
Parhaat käytännöt
Koska poikkeukset heikentävät suorituskykyä niin sovelletaan joitain yleisiä ohjeita:
- Nostetaan poikkeuksia vain silloin kuin tehtävä, joka olisi pitänyt onnistua, ei voitu suorittaa.
- Ei käytetä poikkeuksia osana odotettua ohjelman suoritusta. Sen sijaan lisätään tarkistuksia tavallisten virheiden ehtoihin ja palautetaan virhearvot perinteiseen tapaan.
- Mutta nostetaan poikkeus, jos on kriittinen virhe havaitaan; ohjelmoijat voivat unohtaa tarkistaa palautetut virhearvot.
- Nimeämiskäytäntö: Etuliite poikkeusluokan nimillä, joka on iso E-kirjain.
- Uudelleen nostetaan poikkeus
except
-lohkossa käyttämälläraise
käskyä jos ei kyetä toipumaan ongelmasta; tämä säilyttää alkuperäisen poikkeuksen callstackin. - Pitää olla varovainen, kun käytetään catch-all
Exception
luokkaa, koska alla oleva koodi, käyttöjärjestelmä tai tiedostojärjestelmä saattaa tuottaa odottamattoman poikkeuksen, joka saattaa mennä tällöin poikkeustilanteesta läpi, mikä voi mahdollisesti pilata ohjelman suorituksen. - Pidetään poikkeusten käsittely pois koodista, joka on suoritettava mahdollisimman nopeasti.
Suorituskyky
Kääntäjän optimointitasot ei tuo paljon eroja poikkeuksiin. Kaikissa poikkeuslohkoissa on pieni määrä "kehyskoodia", jota ei voida optimoida.
Jotta saadaan parempi tuntuma, mitä tapahtuu, kokeile pienen testiohjelman kirjoittamista ja kääntämistä -a -kytkimellä. Tämä tekee ihmisen luettavissa olevan assemblytiedosto.
Try
-lauseessa lisätään ylimääräisiä osoitteen laskemista, pinoon laittoa (push) ja siitä poistoa (pop), joitakia suoria hyppykäskyjä ja ehdollisen hypyn.Except
-lause lisää yllä olevan pinoon laittoa (push) ja siitä poistoa (pop), enemmän suoria hyppykäskyjä ja toisen ehdollisen hypyn.Finally
-lause lisää pinosta poiston (pop) ja ehdollisen hyppyn, jotta poikkeus voidaan nostaa uudelleen.Raise
-lause luovat merkkijonon ja ohittaa FPC:n hallinnan poikkeuksen noston.Raise
-lause luovat myös poikkeuskehyksen kyseiselle funktiolle / -menetelmälle, vaikka Raise-lausetta ei toteuttettaisi. Siksi esim. säiliötyypeissä näkee usein, että raise-komento siirretään erilliseen paikalliseen (yksityiseen) aliohjelmaan. Tällöin aliohjelmalla on poikkeuskehys, mutta vain silloin, kun se toteutetaan.
Lisäksi, jos halutaan ihmisen luettavissa olevan callstack:n virheenjäljityksen apuna niin käytetään SysUtils käännösyksikön funktioita ExceptAddr
, ExceptFrames
, ExceptFrameCount
ja BackTraceStrFunc
, tosin se vaatii aikaa vievää pinoon siirtämistä ja merkkijonojen käsittelyä.
Kuten sanottiin, että raskas koodin käsittely kyseisen kohdan ulkopuolella poikkeuksella yleensä ylittää niiden suorituskykyvaikutukset. Ei pidä tuntea pahaa siitä, että pystyy kirjoittamaan parempaa ohjelmakoodia.
Katso myös
Avoiding implicit try finally section
Exceptions vs Error codes - a situation where exceptions might be a danger in some code (see middle of this page)