HyperLink
Bejelentkezés
E-mail: 
Jelszó: 





Skip Navigation Links
 

Hibakezelés a Delphi-ben


Hibakezelés 2. rész

Példaprogram letöltése

6695 bájt

A Delphi-s hibakezelési lehetőségeket tovább vizsgálva mostani cikkünkben a következőkkel ismerkedhetünk meg:
egymásba ágyazott hibakezelés
lefoglalt erőforrás felszabadítása hiba esetén
hibagenerálás programból

A mellékelt példában lévő egyes nyomógombok lenyomásakor különféle hibák keletkeznek, melyeken keresztül bemutatjuk a lehetséges hibakezelési módokat. Nézzük sorra mindegyik gombot.

Az elsőnél arra láthatunk példát, hogy miként lehet két try-exept-end blokkot egymásba ágyazni. Az első blokkot nevezzük a külső blokknak, mivel a második ezen belül helyezkedik el, így ez lesz a belső. A belső blokk a külső try és except kulcsszava közé kerül. Amikor hiba történik a külső blokkban, akkor nyilvánvaló, hogy az ehhez tartozó except utáni sornál folytatódik a program. Mivel a külső blokkban több soros forráskód van, így elvileg bárhol történhet hiba, melyet mindig csak az egyetlen except után kezelhetnénk le, hacsak nem helyezünk el az egyik blokkba egy újabbat. Ilyenkor, ha belső blokk try-except kulcsszava között történik a hiba, akkor már külön hibakezelőt készíthetünk hozzá.
try
   …
   //ha itt hiba történik, akkor a hibakezelés 1 fut le
   …
   try
     … 
     //ha itt hiba történik, akkor a hibakezelés 2 fut le
     …
   except
     … //hibakezelés 2.
   end;
   … 
   //ha itt hiba történik, akkor a hibakezelés 1 fut le
   …
except
   … //hibakezelés 1.
end;

A mellékelt példa második nyomógombjánál arra láthatunk megoldást, hogy miként lehetséges egy lefoglalt erőforrást - jelen esetben memóriát - felszabadítani olyan esetben, ha hiba történik. Ehhez egy eddig nem használt kulcsszót kell felhasználnunk, mely finally névre hallgat. Ez hasonló az except-hez. Ennél is egy try-finally-end blokkot kell létrehoznunk. Tudjuk, hogy a try-except-end esetén a try és except közötti kód minden esetben lefut, és ha hiba történik, akkor kerül sor az except és end közötti részre. Ha nincs hiba, akkor az except és end közötti rész nem kerül sorra. A try-finally-end blokknál annyiban módosul ez a feltételrendszer, hogy a try és finally közötti rész mindenképpen lefut, ha hiba történik, akkor a finally és end közötti részre kerül a vezérlés, ha viszont nincs hiba a finally és end közötti rész, akkor is lefut, ellentétben a try-except-end blokkal.

Ha tehát lefoglalunk valamilyen erőforrást, például oly módon, hogy létrehozunk egy objektumot, mint a TStringList, akkor ezt fel is kell szabadítanunk. Ha viszont a Create és Free hívása között hiba történik, akkor a programunk futása már nem ér el a Free utasításig, mely elvégezné a lefoglalt memória felszabadítását. Ha viszont az objektum létrehozása után egy try-finally-end blokkot hozunk létre úgy, hogy a finally-end közé a lefoglalt objektum felszabadítását végző kód kerül, akkor ez - akár történik hiba, akár nem - mindenképpen le fog futni.
procedure TForm1.Button2Click(Sender: TObject);
var
  a, b, c: double;
  list: TStringList;
begin
  list:=TStringList.Create;
  try
    a:=10;
    b:=0;
    c:=a/b;
    list.Add(Format('%g', [c]));
  finally
    list.Free;
  end;
end;

A harmadik nyomógombnál lévő példában azt láthatjuk, hogy miként tudjuk a hibát egyedi módon lekezelni úgy, hogy közben az erőforrást is felszabadítjuk. Ehhez egy try-finally-end blokkba ágyazott try-except-end blokkra lesz szükségünk. A try-finally-end biztosítja, hogy hiba esetén is fel legyen szabadítva a lefoglalt memória terület, míg a belső blokként elhelyezett try-except-end segítségével, ha történik hiba, akkor azt egyedi módon kezelhetjük.

Ez a feladat egy blokkal nem oldható meg, hiszen az objektum felszabadításának mindenképpen futnia kell, ha történt hiba, ha nem, míg a hibakezelésre csak akkor van szükségünk, ha ténylegesen történt hiba a program futása közben.
procedure TForm1.Button3Click(Sender: TObject);
var
  a, b, c: double;
  list: TStringList;
begin
  list:=TStringList.Create;
  try
    try
      a:=10;
      b:=0;
      c:=a/b;
      list.Add(Format('%g', [c]));
    except
      Label3.Caption:='hiba';
    end;
  finally
    list.Free;
  end;
end;

A negyedik nyomógombnál arra láthatunk példát, hogy miként kezelhető le olyan hiba, mely egy másik eljárásban, vagy függvényben történt.

Ez a feladat különösebb problémát nem okoz. Eddigi ismereteink alapján egyszerűen egy try-except-end blokkban kezelhetjük. Ha az APerB nevű függvény futása során hiba történik, akkor az except kulcsszó után folytatódik a program.
procedure TForm1.Button4Click(Sender: TObject);
begin
  try
    Label4.Caption:=Format('%g', [APerB]);
  except
    Label4.Caption:='hiba';
  end;
end;
Bonyolítsuk kissé az előző helyzetet. Tegyük fel, hogy az APerB függvény maga kezeli a hibát, ekkor mi történik vajon, ha a hívásánál is használunk try-except-end blokkot? Ehhez létrehoztunk az APerB2 függvényt. Itt egy osztást végzünk nullával, így várhatóan hibát kapunk, de ezt rögtön egy try-except-end blokkal még az APerB2-n belül le is kezeljük.
function TForm1.APerB2: double;
var
  a, b: double;
begin
  try
    a:=10;
    b:=0;
    result:=a/b;
  except
    ShowMessage('APerB2: hiba');
    result:=0;
  end;
end;
Amikor az ötödik nyomógomb lenyomásával meghívjuk az APerB2 függvényt, akkor itt szintén egy try-except-end blokkot alkalmazunk.
procedure TForm1.Button5Click(Sender: TObject);
begin
  try
    Label5.Caption:=Format('%g', [APerB2]);
  except
    Label5.Caption:='hiba';
  end;
end;
Viszont mivel a hibát már kezeltük az APerB2 függvényben, így a nyomógomb hívásánál lévő try-except-end nem érzékeli a hibát. Lehet viszont olyan eset is, hogy pont ennek az ellenkezőjére lenne szükségünk. Vagyis ha az APerB2 függvénynél történik hiba, akkor az ottani hibakezelés után még a hívó eljárásban is szeretnénk tudomást kapni arról, hogy történt hiba.

Ennek megvalósításához egy újabb kulcsszó ismerete szükséges, mégpedig a raise-é. A hatodik nyomógombnál hasonló kódot futtatunk, mint az ötödiknél. Itt viszont az APerB3 függvényt hívjuk, amelyet kissé módosítottunk az APerB2-höz képest. Amikor az APerB3-ban hiba történik és az except kulcsszó után fut tovább a program, akkor a hibakezelésünk végeztével - mely egy üzenet kiírásából áll - a raise kulcsszó segítségével újra generáljuk az imént kezelt hibát. Ettől kezdve a hibajelenség pont úgy fenn áll, mintha nem is használtunk volna try-except-end blokkot. Így viszont a APerB3-at hívó eljárásban már megfoghatjuk ezt a hibát a try-except-end blokk között.



Cikksorozat



Könyv
Ez a cikk megtalálható ebben a könyvben: Delphi Software Offline 2000 évkönyv 544. oldal

Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!

Copyright © 1999-2012 Animare Software Kft. Minden jog fenntartva!
| Készült: Animare Stúdió | Adatvédelem | Kapcsolat |