Difference between revisions of "Exceptions/fi"

From Free Pascal wiki
Jump to navigationJump to search
(Created page with "{{Exceptions}} =Poikkeukset= Free Pascal tukee poikkeuksia. Poikkeukset ovat hyödyllisiä virheiden käsittelyssä ja resurssien vuotojen välttämisessä. Muista kuitenkin...")
 
 
(3 intermediate revisions by one other user not shown)
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 Reference guide chapter 17].
  
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 <code>try</code>, <code>raise</code>, <code>except</code> ja <code>finally</code> avainsanat 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öä.
+
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" inline>try</syntaxhighlight>]], [[Raise/fi|<syntaxhighlight lang="pascal" inline>raise</syntaxhighlight>]], [[Except/fi|<syntaxhighlight lang="pascal" inline>except</syntaxhighlight>]] ja [[Finally/fi|<syntaxhighlight lang="pascal" inline>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 <code>Exception</code> löytyy SysUtils [https://www.freepascal.org/docs-html/rtl/sysutils/exception.html] käännösyksiköstä. Kaikissa poikkeuksissa tulisi käyttää tätä luokkaa tai jotain siitä johdettua luokkaa.
+
Poikkeusten kantaluokka <syntaxhighlight lang="pascal" inline>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.
 +
 
 +
SysUtils luo automaattisesti peruspoikkeusten kiinnioton, joten mikä tahansa muutoin jäänyt poikkeus näkyy ihmisen luettavissa muodossa, kun ohjelma päättyy. Luodaksesi luettavia callstacks omasta koodistasi pyydetyistä poikkeuksista, ei välttämättä lopeta ohjelmaa, voidaan käyttää SysUtils-functions <syntaxhighlight lang="pascal" inline>ExceptAddr</syntaxhighlight>, <syntaxhighlight lang="pascal" inline>ExceptFrames</syntaxhighlight>, <syntaxhighlight lang="pascal" inline>ExceptFrameCount</syntaxhighlight>, and <syntaxhighlight lang="pascal" inline>BackTraceStrFunc</syntaxhighlight>.
  
  
 
== Esimerkit ==
 
== Esimerkit ==
  
Huomaa, että Pascal käyttää eri avainsanoja kuin jotkut muut kielet: <code>raise</code> vastaa <code>throw</code>:ta ja <code>except</code> vastaa <code>catch</code>:a.
+
Huomaa, että [[Pascal/fi|Pascal]] käyttää eri [[Keyword|avainsanoja]] kuin jotkut muut kielet: <syntaxhighlight lang="pascal" inline>raise</syntaxhighlight> vastaa <syntaxhighlight lang="pascal" inline>throw</syntaxhighlight>:ta ja <syntaxhighlight lang="pascal" inline>except</syntaxhighlight> vastaa <syntaxhighlight lang="pascal" inline>catch</syntaxhighlight>:a.
Myös kääntäjä on suunniteltu niin että valinnan mukaan kukin <code>try</code>-lohko voidaan yhdistää joko <code>except</code> tai <code>finally</code>-lohkoon, mutta ei molempiin samanaikaisesti. Jos tarvitaan sekä <code>except</code> että <code>finally</code>-lohkoa suojaamaan samaa koodia niin ne laitetaan sisäkkäin.
+
Myös kääntäjä on suunniteltu niin että valinnan mukaan kukin <syntaxhighlight lang="pascal" inline>try</syntaxhighlight>-lohko voidaan yhdistää joko <syntaxhighlight lang="pascal" inline>except</syntaxhighlight> tai <syntaxhighlight lang="pascal" inline>finally</syntaxhighlight>-lohkoon, mutta ei molempiin samanaikaisesti. Jos tarvitaan sekä <syntaxhighlight lang="pascal" inline>except</syntaxhighlight> että <syntaxhighlight lang="pascal" inline>finally</syntaxhighlight>-lohkoa suojaamaan samaa koodia niin ne laitetaan sisäkkäin.
  
 
=== Virheiden käsittely ===
 
=== Virheiden käsittely ===
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
try
+
uses sysutils;
 +
 
 +
begin
 +
  try
 
   // Tee jotain, joka saattaa mennä pieleen.
 
   // Tee jotain, joka saattaa mennä pieleen.
except
+
  except
  on E : Exception do begin
+
    on E : Exception do begin
 
     // Yritä palauttaa tai näytä käyttäjälle virheilmoitus
 
     // Yritä palauttaa tai näytä käyttäjälle virheilmoitus
 +
    end;
 
   end;
 
   end;
end;
+
end.
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=== Resurssien siivoaminen ===
 
=== Resurssien siivoaminen ===
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 
try
 
try
 
   // Tee jotain, joka saattaa mennä pieleen.
 
   // Tee jotain, joka saattaa mennä pieleen.
Line 40: Line 46:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
=== Poikkeusten vuoto ===
 +
 +
Finally-lohkot eivät aina tuhoa poikkeusolioita. Kaikki poikkeukset, jotka saavuttavat ohjelman "lopun". käynnistää muistivuodon varoituksen. Tällaisten poikkeusten kuluttamiseen voidaan käyttää ylimääräistä poikkeuslohkoa. Tämä koskee
 +
[https://bugs.freepascal.org/view.php?id=33650 Delphi-yhteensopivuus].
 +
 +
<syntaxhighlight lang="pascal">
 +
begin
 +
  try
 +
    // Pääohjelma, jossa luodaan poikkeusolio.
 +
  finally
 +
    try
 +
      // puhdistuskoodi.
 +
    except
 +
    end;
 +
  end;
 +
end.
 +
</syntaxhighlight>
 
=== 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 71:
 
=== 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 57: Line 80:
 
     on E : EMyLittleException do writeln(E.Message);
 
     on E : EMyLittleException do writeln(E.Message);
 
     on E : Exception do writeln('This is not my exception!');
 
     on E : Exception do writeln('This is not my exception!');
 +
    else writeln('This is not an Exception-descendant at all!');
 
   end;
 
   end;
 +
end;
 +
</syntaxhighlight>
 +
 +
=== Poikkeusten uudelleen nostaminen  ===
 +
 +
<syntaxhighlight lang="pascal">
 +
try
 +
  // Tee jotain, joka voi mennä pieleen.
 +
except
 +
  // Yritä palauttaa tai näyttää käyttäjälle virhesanoma.
 +
  if recoveredSuccessfully = FALSE then
 +
    raise;
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 65: Line 101:
  
  
Käännösyksikkö SysUtils määrittelee ja nostaa monia erityisiä poikkeusluokkia: [https://www.freepascal.org/docs-html/rtl/sysutils/index-4.html]
+
Käännösyksikkö SysUtils määrittelee ja nostaa monia erityisiä [https://www.freepascal.org/docs-html/rtl/sysutils/index-4.html poikkeusluokkia]
  
 +
Kun käännösyksikkö SysUtils on mukana ohjelmassa ja poikkeukset on otettu käyttöön, erilaisia [https://www.freepascal.org/docs-html/user/userap4.html runtime-virheitä] muutetaan poikkeuksiksi. Prosessoritason keskeytykset, kuten SIGSEGV tai SIGFPU, jotka yleensä kääntyvät ajonaikaisvirheisiin, muutetaan myös poikkeuksiksi. Esimerkiksi run-time error 200 eli ajonaikainen virhe 200 (nollalla jako) muuttuu EDivByZero:ksi tai EZeroDivide:ksi, kun taas ajonaikainen virhe 216 (yleinen suojausvirhe, general protection fault) tulee EAccessViolation:ksi.
  
 
== Parhaat käytännöt ==
 
== Parhaat käytännöt ==
  
Koska poikkeukset heikentävät suorituskykyä niin sovelletaan joitain yleisiä ohjeita:
+
*Nostetaan poikkeuksia vain silloin kuin toimenpidettä ei voitu saattaa päätökseen, jos se olisi tavallisesti onnistunut.
 
+
* Ei käytetä poikkeuksia osana odotettua ohjelman suoritusta. Sen sijaan lisätään tarkistuksia tavallisten virheiden ehtoihin ja palautetaan virhearvot perinteiseen tapaan. Esimerkiksi syötteen jäsentämiseen liittyvät ongelmat tai tiedoston olemassaolo yleensä eivät ole todella poikkeuksellisia.
* 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.
 
* 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 <code>except</code> -lohkossa käyttämällä <code>raise</code> käskyä jos ei kyetä toipumaan ongelmasta; tämä säilyttää alkuperäisen poikkeuksen callstackin.
+
* Uudelleen nostetaan poikkeus <syntaxhighlight lang="pascal" inline>except</syntaxhighlight> -lohkossa käyttämällä <syntaxhighlight lang="pascal" inline>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 <code>Exception</code> 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.
+
* Pitää olla varovainen, kun käytetään catch-all <syntaxhighlight lang="pascal" inline>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.
 +
* Kun käännösyksikköä tai kirjastoa kirjoitetaan, jos poikkeuksia käytetään niin ne on dokumentoitava selvästi. Näin käännösyksikön käyttäjä tietää, mitä odottaa.
 
* 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 84: Line 120:
 
== Suorituskyky ==
 
== Suorituskyky ==
  
Kääntäjän optimointitasot ei tuo paljon eroja poikkeuksiin. Kaikissa poikkeuslohkoissa on pieni määrä "kehyskoodia", jota ei voida optimoida.
+
Kääntäjän optimointitasot ei tuo paljon eroja poikkeuksiin. Kaikissa poikkeuslohkoissa on pieni määrä "kehyskoodia", jota ei voida optimoida. Toki on mahdollista, että kääntäjä tuottaa poikkeuskoodin, jolla on erilaisia suorituskykyvaikutuksia. FPC 3.0.4: sta lähtien oletuspoikkeusmekanismi käyttää standardia setjmp / longjmp-tyyliä. FPC tukee myös OS-järjestelmään perustuvaa strukturoitua poikkeuksenkäsittelyä; tämä on Win64: n oletusarvo, ja se voidaan ottaa käyttöön Win32: ssä (käännä kääntäjällä uudelleen<syntaxhighlight lang="pascal" inline>$define TEST_WIN32_SEH</syntaxhighlight>). Muita mekanismeja tullaan todennäköisesti lisäämään FPC:hen tulevaisuudessa.
  
 
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.
  
* <code>Try</code>-lauseessa lisätään ylimääräisiä osoitteen laskemista, pinoon laittoa (push) ja siitä poistoa (pop), joitakia suoria hyppykäskyjä ja ehdollisen hypyn.
+
Metodeita setjmp/longjmp koskevat huomautukset:
* <code>Except</code>-lause lisää yllä olevan pinoon laittoa (push) ja siitä poistoa (pop), enemmän suoria hyppykäskyjä ja toisen ehdollisen hypyn.
+
 
* <code>Finally</code>-lause  lisää pinosta poiston (pop) ja ehdollisen hyppyn, jotta poikkeus voidaan nostaa uudelleen.  
+
* <syntaxhighlight lang="pascal" inline>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.
* <code>Raise</code>-lause luovat merkkijonon ja ohittaa FPC:n hallinnan poikkeuksen noston.
+
* <syntaxhighlight lang="pascal" inline>Except</syntaxhighlight>-lause lisää yllä olevan pinoon laittoa (push) ja siitä poistoa (pop), enemmän suoria hyppykäskyjä ja toisen ehdollisen hypyn. Tämä on poikkeuskehyksen asetus "kustannus", vaikka poikkeusta ei esiintyisi.
* <code>Raise</code>-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.  
+
* <syntaxhighlight lang="pascal" inline>Finally</syntaxhighlight>-lause  lisää pinosta poiston (pop) ja ehdollisen hyppyn, jotta poikkeus voidaan nostaa uudelleen.  
 +
* <syntaxhighlight lang="pascal" inline>Raise</syntaxhighlight>-lause luovat merkkijonon ja ohittaa FPC:n hallinnan poikkeuksen noston.
 +
* <syntaxhighlight lang="pascal" inline>Raise</syntaxhighlight>-lause luovat merkkijonon ja välittävät ohjauksen FPC: n poikkeustarkistukseen. Merkkijonon luominen itsessään voi synnyttää implisiittisen poikkeuskehyksen funktiolle / aliohjelmalle dynaamisten merkkijärjestelyjen vuoksi, vaikka raise ei toteutuisi. Siksi esim. konttityypit näkevät usein raisen erillisenä paikallisena (yksityisenä) aliohjelmana. Tämä lokalisoi poikkeusrungon kyseiseen aliohjelmaan, joten suorituskyvyn osuma toteutetaan vain, jos aliohjelmaa kutsutaan.
  
  
Lisäksi, jos halutaan ihmisen luettavissa olevan callstack:n virheenjäljityksen apuna niin käytetään SysUtils käännösyksikön funktioita <code>ExceptAddr</code>, <code>ExceptFrames</code>, <code>ExceptFrameCount</code> ja <code>BackTraceStrFunc</code>, tosin se vaatii aikaa vievää pinoon siirtämistä ja merkkijonojen käsittelyä.
+
Lisäksi ihmisen luettavissa olevan callstackin luominen korotetusta poikkeuksesta käsittää aikaa vievän pinonsiirron ja merkkikäsittelyn.
  
 
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.  
  
 
== Katso myös ==
 
== Katso myös ==
 
 
[[try]]
 
  
 
[[Logging exceptions]]
 
[[Logging exceptions]]

Latest revision as of 16:23, 6 August 2022

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ä: Reference guide chapter 17.

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 [1] käännösyksiköstä. Kaikissa poikkeuksissa tulisi käyttää tätä luokkaa tai jotain siitä johdettua luokkaa.

SysUtils luo automaattisesti peruspoikkeusten kiinnioton, joten mikä tahansa muutoin jäänyt poikkeus näkyy ihmisen luettavissa muodossa, kun ohjelma päättyy. Luodaksesi luettavia callstacks omasta koodistasi pyydetyistä poikkeuksista, ei välttämättä lopeta ohjelmaa, voidaan käyttää SysUtils-functions ExceptAddr, ExceptFrames, ExceptFrameCount, and BackTraceStrFunc.


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

uses sysutils;

begin
  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;
end.

Resurssien siivoaminen

try
  // Tee jotain, joka saattaa mennä pieleen.
finally
  // Siivoa resurssi lopuksi (kutsutaan aina, myös poikkeus tilanteissakin).
end;

Poikkeusten vuoto

Finally-lohkot eivät aina tuhoa poikkeusolioita. Kaikki poikkeukset, jotka saavuttavat ohjelman "lopun". käynnistää muistivuodon varoituksen. Tällaisten poikkeusten kuluttamiseen voidaan käyttää ylimääräistä poikkeuslohkoa. Tämä koskee Delphi-yhteensopivuus.

begin
  try
    // Pääohjelma, jossa luodaan poikkeusolio.
  finally
    try
      // puhdistuskoodi.
    except
    end;
  end;
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!');
    else writeln('This is not an Exception-descendant at all!');
  end;
end;

Poikkeusten uudelleen nostaminen

try
  // Tee jotain, joka voi mennä pieleen.
except
  // Yritä palauttaa tai näyttää käyttäjälle virhesanoma.
  if recoveredSuccessfully = FALSE then
    raise;
end;


Poikkeusluokat

Käännösyksikkö SysUtils määrittelee ja nostaa monia erityisiä poikkeusluokkia

Kun käännösyksikkö SysUtils on mukana ohjelmassa ja poikkeukset on otettu käyttöön, erilaisia runtime-virheitä muutetaan poikkeuksiksi. Prosessoritason keskeytykset, kuten SIGSEGV tai SIGFPU, jotka yleensä kääntyvät ajonaikaisvirheisiin, muutetaan myös poikkeuksiksi. Esimerkiksi run-time error 200 eli ajonaikainen virhe 200 (nollalla jako) muuttuu EDivByZero:ksi tai EZeroDivide:ksi, kun taas ajonaikainen virhe 216 (yleinen suojausvirhe, general protection fault) tulee EAccessViolation:ksi.

Parhaat käytännöt

  • Nostetaan poikkeuksia vain silloin kuin toimenpidettä ei voitu saattaa päätökseen, jos se olisi tavallisesti onnistunut.
  • Ei käytetä poikkeuksia osana odotettua ohjelman suoritusta. Sen sijaan lisätään tarkistuksia tavallisten virheiden ehtoihin ja palautetaan virhearvot perinteiseen tapaan. Esimerkiksi syötteen jäsentämiseen liittyvät ongelmat tai tiedoston olemassaolo yleensä eivät ole todella poikkeuksellisia.
  • 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.
  • Kun käännösyksikköä tai kirjastoa kirjoitetaan, jos poikkeuksia käytetään niin ne on dokumentoitava selvästi. Näin käännösyksikön käyttäjä tietää, mitä odottaa.
  • 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. Toki on mahdollista, että kääntäjä tuottaa poikkeuskoodin, jolla on erilaisia suorituskykyvaikutuksia. FPC 3.0.4: sta lähtien oletuspoikkeusmekanismi käyttää standardia setjmp / longjmp-tyyliä. FPC tukee myös OS-järjestelmään perustuvaa strukturoitua poikkeuksenkäsittelyä; tämä on Win64: n oletusarvo, ja se voidaan ottaa käyttöön Win32: ssä (käännä kääntäjällä uudelleen$define TEST_WIN32_SEH). Muita mekanismeja tullaan todennäköisesti lisäämään FPC:hen tulevaisuudessa.

Jotta saadaan parempi tuntuma, mitä tapahtuu, kokeile pienen testiohjelman kirjoittamista ja kääntämistä -a -kytkimellä. Tämä tekee ihmisen luettavissa olevan assemblytiedosto.

Metodeita setjmp/longjmp koskevat huomautukset:

  • 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. Tämä on poikkeuskehyksen asetus "kustannus", vaikka poikkeusta ei esiintyisi.
  • 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 merkkijonon ja välittävät ohjauksen FPC: n poikkeustarkistukseen. Merkkijonon luominen itsessään voi synnyttää implisiittisen poikkeuskehyksen funktiolle / aliohjelmalle dynaamisten merkkijärjestelyjen vuoksi, vaikka raise ei toteutuisi. Siksi esim. konttityypit näkevät usein raisen erillisenä paikallisena (yksityisenä) aliohjelmana. Tämä lokalisoi poikkeusrungon kyseiseen aliohjelmaan, joten suorituskyvyn osuma toteutetaan vain, jos aliohjelmaa kutsutaan.


Lisäksi ihmisen luettavissa olevan callstackin luominen korotetusta poikkeuksesta käsittää aikaa vievän pinonsiirron ja merkkikäsittelyn.

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

Logging exceptions

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)