1 / 45

KIVÉTELKEZELÉS

KIVÉTELKEZELÉS. Programozási nyelvek összehasonlító elemzése. Készítette: Pásztor Attila KF GAMF ELTE-IK DOKTORI ISKOLA PHD hallgató. KIVÉTELKEZELÉS. Tartalom:. Kivételkezelés, kivétel fogalmai Kezeletlen kivétel ”Kivételkezelés” a C nyelvben

baird
Download Presentation

KIVÉTELKEZELÉS

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. KIVÉTELKEZELÉS Programozási nyelvek összehasonlító elemzése Készítette: Pásztor Attila KF GAMFELTE-IK DOKTORI ISKOLAPHD hallgató

  2. KIVÉTELKEZELÉS Tartalom: • Kivételkezelés, kivétel fogalmai • Kezeletlen kivétel • ”Kivételkezelés” a C nyelvben • A kivételkezelés kezdetei : FORTRAN, COBOL, PL/I • Fejlett kivételkezelés :C++, JAVA, C# • Kivételkezelés adatbáziskezelő nyelvekben : TSQL, PLSQL, FOXPRO • Egyebek • Összefoglalás

  3. Elvárás: az előllított program helyesen és megbízhatóan működjön Alapvető elvárás: helyes - a specifikációnak megfelelően működik robosztus – semmilyen körülmények között sem okozzon nem várt mellékhatást, katasztrófát

  4. Kezeletlen kivétel class Program { static void Main(string[] args) { int a = Beolvas("z els"); int b = Beolvas(" második"); int c = a + b; Console.WriteLine("A két szám összege: {0}", c); } static int Beolvas(string Aktuális) { Console.Write("A"+Aktuális+" szám: "); string s = System.Console.ReadLine(); int a = int.Parse(s); return a; } }

  5. Kivétel : olyan futás közben fellépő hiba ami megszakítja az utasítások normál futási sorrendjét A programok futása közben hibák léphetnek fel. • Szoftverhibák • a futtatott programban, • kísérlet zérus osztásra • null pointer értékre való hivatkozás • aritmetikai túlcsordulás, alulcsordulás • tömb hibás indexelése • hibás típus konverzió kísérlete • hibás input stb. • az operációs rendszerben meglévő programozói hibák. • Hardverhibák • elromlott winchester miatti leállások, • elfogy a memória, stb.

  6. Kivételkezelés feladata : • olyan események kezelése melyek nehézzé, vagy lehetetlenné teszik a program normál módú folytatását • a futási hibák kijavítása (ha lehetséges), vagy a program leállítása úgy, hogy a legkisebb hibák keletkezzenek Kivételkezelés régen : - abortált a program :-( - minden alprogram valamilyen jelzést (hibaértéket) ad vissza, hogy a lefutás OK., vagy nem:

  7. ”Kivételkezelés” a C nyelvben intFGV() { FILE *ifptr=NULL; FILE *ofptr=NULL; char *bet=NULL; bet=calloc(1,1); ifptr=fopen("C:\\szöveg.txt","r"); ofptr=fopen("C:\\uj.txt","w"); do{ *bet=getc(ifptr); putc(*bet,ofptr); }while(!feof(ifptr)); fclose(ifptr); fclose(ofptr); free(bet); return 0; } Nem megbízható program ! Megoldások: 1-hibakezelés helyben a „veszélyes” helyeken 2- közös hibakezelő rész

  8. ”Kivételkezelés” a C nyelvben - hibakezelés helyben int FGV() { FILE *ifptr=NULL; FILE *ofptr=NULL; char *bet=NULL; bet=calloc(1,1); if(bet==NULL){printf(”kevés memória! "); getch(); return 1;} ifptr=fopen("C:\\szöveg.txt","r"); if(ifptr==NULL) {printf("HIBAS MEGNYITAS Olvasasra");free(bet);return 2;} ofptr=fopen("C:\\uj.txt","w"); if(ofptr==NULL) {printf("HIBAS MEGNYITAS Irasra"); fclose(ofptr);free(bet); getch();return 3;} do { *bet=getc(ifptr); //……….. További lehetőségek putc(*bet,ofptr); } while(!feof(ifptr)); fclose(ifptr); fclose(ofptr); free(bet); return 0; }

  9. ”Kivételkezelés” a C nyelvben- közös hibakezelő rész int FGV() { FILE *ifptr=NULL; FILE *ofptr=NULL; char *bet; bet=calloc(1,1); if(bet==NULL) goto hiba; ifptr=fopen("c:\\szoveg.txt","r"); if(ifptr==NULL)goto hiba; ofptr=fopen("c:\\uj.txt","w"); if(ofptr==NULL)goto hiba; do{ *bet=getc(ifptr); putc(*bet,ofptr); } while(!feof(ifptr)); hiba: if(ifptr!=NULL)fclose(ifptr); else{ printf("HIBA..");getch();} if(ofptr!=NULL)fclose(ofptr); else{ printf("HIBA..");getch();} if(bet!=NULL)free(bet); else{ printf("HIBA..");getch();} return 0; }

  10. Kivételkezelés kezdetei - FORTRAN • Csak input – output műveletek közbeni hibák kezelése • err paraméter a hibakezelő rész címkéjével open(file=’proba.file’,err=100, unit=2) . . . 100 write(*,110) 110 format(’Hiba’)

  11. Kivételkezelés kezdetei - COBOL • Aritmetikai műveletek hibáinak kezelése • Input –output műveletek közbeni hibák kezelése 1, DIVIDE N1 BY N2 GIVING N3 REMINDER N4 - eseti jellegű hibakezelés ON SIZE ERROR DISPLAY ” HIBA” - mint a FORTRAN-ban 2, PROCEDURE DIVISION. DECLERATIVES. Hiba SECTION. USE AFTER EXCEPTION PROCEDURE ON SajatFile. Hibakezeles2. DISPLAY ”HIBA” END DECLERATIVES

  12. Kivételkezelés kezdetei – PL/I • Kezdetleges kivételkezelő mechanizmus (60-as évek) • Néhány beépített kivétel pl. ZERODIVIDE • A kivételeknek nevük van, nem lehet – paraméterezni – csoportosítani • Lehet saját kivételt készíteni – CONDITION • Lehet kivételt dobni - SIGNAL

  13. Elvárások a kivételkezeléssel szemben meg tudjuk különböztetni a hibákat, a hibát kezelő kód különüljön el a tényleges kódtól, megfelelően tudjuk kezelni - a hiba könnyen jusson el arra a helyre, ahol azt kezelni kell, kötelező legyen kezelni a hibákat

  14. Megoldás elemzése: Az első elvárás, hogy meg tudjuk különböztetni a hibákat - ez általában a fellépés helyén történik. A második elvárás azt szeretné elérni, hogy a programot először látó ember is azonnal el tudja különíteni a hibakezelő és a működésért felelős részeket. Ez könnyebben továbbfejleszthető, karbantartható programokhoz vezet.

  15. A hiba jusson el oda, ahol kezelni kell A harmadik elvárás arra vonatkozik, hogy - mivel a programok többszintűek -, egy alacsonyabb szinten jelentkező hibát (például ha egy fájlt nem tudunk megnyitni, egy üres veremből akar valaki kiolvasni) nem biztos, hogy az adott szint le tud kezelni, ezért a megfelelő helyre kell eljuttatni.

  16. Programnyelvek kivételkezeléseinek összehasonlítási szempontjai: Hiba- vagy kivételkezelést ad-e a nyelv? Hogyan kell kivételeket definiálni-kiváltani-kezelni? Milyen a kivételkezelés szintaktikai formája / Mihez kapcsolódik a kezelés: utasítás-, blokk- vagy eljárás/függvényszintű? A kivételekből lehet-e kivételcsoportokat, kivételosztályokat képezni, amelyeket a kivételkezelőben egységesen lehet kezelni? Paraméterezhető-e a kivétel információ továbbadás céljából? A kivétel kezelése után honnan folytatódjon a program?

  17. Programnyelvek kivételkezeléseinek összehasonlítási szempontjai Van –e olyan nyelvi elem amely mind kivételes mind normál módú futás esetén végrehajtódik („finally”) ? Tovább dobódhat-e a kivétel? Mi történik a kezeletlen kivétellel? Megadható-e /meg kell-e adni, hogy egy alprogram milyen lekezeletlen kivételeket küldhet? Párhuzamos környezetben vannak-e speciális kivételek? Mi történik a váratlan kivételekkel? Kiváltható-e kivétel kivételkezelőben? Melyik kivételkezelő kezeli a kivételt?

  18. Fejlett kivételkezelés :C++ • try { • // kivétel keletkezhet • } • catch( típus [név]){ • // kivétel kezelése • } • - Egy try blokkhoz több catch ág is tartozhat (mindegyik a saját kiv. tipust kapja el • - catch(…) esetén minden kivételt elkap • bármilyen típusú változót el lehet dobni kivételként • kivétel dobása throw • try { • // mindenféle kivétel keletkezhet • } • catch( ….){ • // minden kivételt elkap • }

  19. Fejlett kivételkezelés :C++ • int main() { • FILE *fptr; • try { • fptr=fopen("c:\\kw.txt", "r"); • if( fptr ==NULL ) throw "baj van"; • } • catch(int) {cout << "Exception1" ;} • catch(float){cout << "Exception2" ;} • catch(...) {cout << "Exception3" ; } • fclose(fptr); • } • - nincs finally • kezeletlen kivétel továbbadódik a hívó függvény felé, ha a main() sem kezeli meghívódik a terminate függvény => alapesetben az abort függvényt hívja ez leállítja a prg. futását • a kivétel kezelése után a vezérlés nem kerül vissza abba a blokkba ahol a kivétel keletkezett – destruktor problémák (két dobott kivétel)

  20. Fejlett kivételkezelés :C++ finally hiányának kezelése class File{ private:FILE *f; public: File(char *filenev) { f=fopen(filenev,"r"); } ~File(){fclose(f); cout<<"lezártam";} }; void Fgv() { File f("c:\\k.txt"); try{} // itt keletkezhet kiv. catch(...){} // kiv. kez // a destruktor miatt fájl lezárás mindenképpen } int main() {Fgv(); }

  21. Lehetőség függvények fejlécében a dobható kivételek részhalmazát megadni throw "(" [type {"," type}] ")" Pl.: void f1(int x) throw(A,B,C); Az f1 függvény csak A,B és C típusú kivételt generál, vagy azok leszármazottait. int f2(int x) throw () -- f2 nem válthat ki kivételt! void f3 (int x) -- f3 bármit kiválthat! Ha specifikáltunk lehetséges kivételtípusokat, akkor minden más esetben a rendszer meghívja az unexpected() függvényt, melynek alapértelmezett viselkedése a terminate() függvény meghívása. Ez a set_unexpectedsegítségével szintén átállítható. Fejlett kivételkezelés :C++

  22. Példák: class X {}; class Y: public X {}; class Z {}; void A() throw(X,Z) // A X,Y,Z-t dobhat { /* ... */ } void B() throw(Y,Z) { A(); // unexpected, ha A X-t dob, ok Y, Z típusúra } void C(); // semmit sem tudunk C-ről void D() throw() { C(); // ha C bármit kivált, unexpected -t hív throw 7; // unexpected-t hív } Fejlett kivételkezelés :C++

  23. Fejlett kivételkezelés :C++ Előre definiált kivételek : bad_alloc; bad_cast; bad_typeid #include <iostream> using namespace std; int main() { try { double *t = new double [1000000000]; } catch(bad_alloc) { cout << "Elfogyott a memória\n"; } system("pause"); return 0; }

  24. try { ... throw new EgyException (“parameter”); } catch (típus változónév) { ... } finally { ... } Fejlett kivételkezelés :Java

  25. a C++ szintaxistól nem sokban különbözik. A kivételek mindig objektumok. finally nyelvi konstrukció, ezzel a Java megbízhatóbb programok írását segíti elő. Nincs catch(…) helyette catch(Exception e) Fejlett kivételkezelés :Java

  26. Egy függvény által kiváltható kivételek specifikálása: void f(int x)throws EgyikException, MasikException; Minden kivétel a java.lang.Throwable leszármazottja. Ha olyan kivételt szeretnénk dobni, amely nem a Throwable gyermeke, akkor az fordítási hibát okoz. publicclass ExExample {          void method1() { try {                         method2(3);                 } catch (Exception e) { e.printStackTrace(); }         }                void method2(int i) throwsException{                if (i == 0) trownewException("illegal argument: 0");         } } Fejlett kivételkezelés :Java

  27. A kivételek két nagy csoportba sorolhatóak: ellenőrzöttek: Exception leszármazottjai Az ellenőrzött kivételek esetén fordítási hiba lép fel, ha nincsenek specifikálva vagy elkapva; illetve ha olyan ellenőrzött kivételt kívánunk elkapni, amely hatókörön kívül van. nem-ellenőrzöttek: Error leszármazottjai Futási időben keletkeznek nem kötelező elkapni őket Fejlett kivételkezelés :Java

  28. Azért volt arra szükség, hogy a kivételeket a fenti két csoportba sorolják, mert számos olyan kivétel van, amely előre nem látható és fölösleges lenne mindenhol lekezelni őket. Ezeket a kivételeket nevezzük nem-ellenőrzött kivételeknek. Például nem ellenőrizzük le minden utasítás végrehajtása előtt, hogy van-e elég memóriánk stb. Fejlett kivételkezelés :Java

  29. Fejlett kivételkezelés :Java Néhány predefinit nem ellenőrzött kivétel (a RuntimeException leszármazottjai): ArithmeticException, ClassCastException, IndexOutOfBoundsException,két alosztálya: ArrayIndexOutOfBoundsException,StringIndexOutOfBoundsException, NullPointerException. az Error leszármazottjai pl. OutOfMemoryError,StackOverflowError, stb.

  30. Fejlett kivételkezelés :Java predefinit kivételek előfordulása: class A {// ... } class B extends A {// ... } class C { void X() { A a= new A; B b=(B)a; // ClassCastException } void Y() { int ia[]= new int[10]; for (int i=1; i<=10; i++)ia[i]=0; /* amikor i==10 lesz, ArrayIndexOutOfBoundsException */ } void Z() { C c=null; c.X(); // NullPointerException } }

  31. Fejlett kivételkezelés :Java Kivételek kezelése try { // utasítások } catch (MyException e) { // utasítások MyException kezelésére } catch (AnotherException e) { // utasítások AnotherException kezelésére } catch (Exception e) { // utasítások AnotherException kezelésérefinally { // mindig végrehajtódóutasítások } Fontos a catch ágak sorrendje

  32. class Program { static void Main(string[] args) { string s = "asdfg"; int a = 0; try { a = int.Parse(s); Console.WriteLine(a); } catch (FormatException exc) { Console.WriteLine(exc.Message); } Console.ReadKey(); } } Fejlett kivételkezelés :C#

  33. Fejlett kivételkezelés :C# Példa 1: using System; class ExceptionTestClass { public static void Main() { int x = 0; try { int y = 100/x; } catch (ArithmeticException e) { Console.WriteLine("ArithmeticException Handler: {0}", e.ToString()); } catch (Exception e) { Console.WriteLine("Generic Exception Handler: {0}", e.ToString()); } } }

  34. using System; class ArgumentOutOfRangeExample { static public void Main() { …. try { … } catch (ArgumentOutOfRangeException e) { Console.WriteLine("Error: {0}",e); } finally { Console.WriteLine(„It is always executed."); } } } Fejlett kivételkezelés :C#

  35. Fejlett kivételkezelés :C# Példapogram a throw használatára; több catch ág class Program { static void Main(string[] args) { string s = "200"; int a = 0; try { a = int.Parse(s); if (a > 100) throw new Exception("nem lehet nagyobb, mint 100!\n"); Console.WriteLine(a); } catch (FormatException ex) { Console.WriteLine(ex.Message); } catch (Exception exc) { Console.WriteLine(exc.Message); } Console.ReadKey(); } } Az a cath kapja el a hibát (felülről lefele haladva) amely formális param. típusa vagy azonos a kivétel objektum típusával vagy őse annak.

  36. Fejlett kivételkezelés :C# • catch - általános cach • { • Console.WriteLine("Hibásan adta meg a számot!"); • . • . • } • Több catch() esetén a fordító hibát jelez, ha rossz a sorrend

  37. Fejlett kivételkezelés :C#

  38. Fejlett kivételkezelés :C# • System.Exception az alkalmazás végrehajtása során elıforduló hibákhoz társított kivételek ősosztálya • System.SystemException a System névtér előre definiált kivételtípusainak ősosztálya • System.ArgumentException egy metódus valamely aktuális paramétere érvénytelen • System.ArgumentNullException null referencia nem megengedett átadása • System.ArgumentOutOfRangeException az átadott paraméter az érvényes tartományon kívülre esik • System.ArithmeticException aritmetikai műveletek és típuskonverzió során előálló kivételek ősosztálya • System.DivideByZeroException nullával történő osztás • System.OverflowException túlcsordulási hiba • System.FormatException a paraméter formátuma nem megfelelő • System.IndexOutOfRangeException tömb túlindexelése • System.IO.IOException fájlkezeléssel kapcsolatos kivételek ősosztálya • System.NotImplementedException a meghívott metódus nem rendelkezik implementációval • System.NullReferenceException egy változón keresztül hivatkozunk egy objektum egy tagjára, és közben a változó null értékű • System.ApplicationException a felhasználó által definiált kivételtípusainak ősosztálya

  39. Fejlett kivételkezelés :C# - kivétel továbbadása class Program { static void Main(string[] args) { string s = "asdfg"; int a = 0; try { a = átalakít(s); Console.WriteLine(a); } catch (Exception exc) { Console.WriteLine(exc.Message); } } public static int átalakít(string s) { return átalakít2(s); } public static int átalakít2(string s) { return int.Parse(s); } }

  40. Kivételkezelés adatbáziskezelő nyelvekben : PLSQL - ORACLE Begin: blokk kezdet, exception : hibaág, when … then : adott hiba kezelése, hiba dobása raise begin select a,b into l_a, l_b from foo where i=1; dbms_output.put_line('a: ' || l_a || ', b: ' || l_b); if (DATE>SYSDATE) then raise date_error endif; exception when date_error then dbms_output.put_line('*** Exc: date_err'); when too_many_rows then dbms_output.put_line('*** Exc: too many rows'); when no_data_found then dbms_output.put_line('*** Exc: no data'); end;

  41. Kivételkezelés adatbáziskezelő nyelvekben : TSQL - MSQL Begin try – end try : a műveleti blokk Begin catch – end catch : a hibakezelő If … : adott hiba kezelése BEGIN TRY ……………….   END TRY   BEGIN CATCH if (error_number() = 1205)             SET ……       else             SET …….. END CATCH

  42. Kivételkezelés adatbáziskezelő nyelvekben : FOXPRO TRY – ENDTRY CATCH : a hibakezelő WHEN … : adott hiba kezeléseTHROW kivételdobás FINALLY TRY [ tryCommands ] [ CATCH [ TO VarName ] [WHEN lExpression ][ catchCommands ] ] [ THROW [ eUserExpression ] ][ EXIT ] [FINALLY[ finallyCommands ] ] ENDTRY

  43. Egyebek : migrációs segédprogramokSQL Loader • Feladata : Adatok átvitele szövegfájlból adatbázisba • Exceptionfile – t hoz létre • Az állományban azok a rekordok lesznek amiket nem sikerült migrálni

  44. Egyebek : Matlab try    /utasítások/catch    /utasítások/end A MATLAB nem nyújt lehetőséget sem újrakezdésre, sem ún. final részre.A catch mindent elkap. • Zéróosztás nem ad hibát a =1; b = -5:0.2:4; % ez egy lista 0.2-sével c = 1:0.2:10; f = a./b; % elemenkénti osztás: ./ g = f*c' % skallár szorzás a c transzponáltjával

  45. Összefoglalás • Hasznos eszköz a legtöbb új nyelvben megtalálható • Előnye, hogy jól elkülöníta a feladatokat megoldó kódot a hibakezeléstől. A progr. átláthatóbb, mógosíthatóbb. • Obj. orientált nyelvekben a konstruktor kivételdobással értesítheti a konstruktor hívóját.( arról értesíthet, hogy miért nem) • Hátrányok : kissé elrontja a program strukturáltságát ( hasonló a goto-hoz). Veszélyes, ha olyankor történik kiv. dobás amikor nem szabadna ( C++ destr.) Esetenként többletkód generálódik. • A kivételek előidézése és kezelése jelentős erőforrás igénnyel jár és lassítja az alkalmazás végrehajtását az újabb osztályok betöltése és a veremkezelési feladatok következtében. • Lehetőleg csökkentsük minimális mértékűre az általunk elıődézett kivételek számát. • Kerüljük újabb kivétel elődézését a finally blokkban, ugyanis ha egy kivételt nem fogunk el egyetlen catch blokkal sem, akkor végrehajtódnak a finally blokkban elhelyezett utasítások, és az újabb kivétel elődizése következtében az eredeti elvész. • Amennyiben egy programszakaszon belül több egymás utáni utasításnál is elképzelhető kivétel keletkezése, úgy ne készítsünk ezekhez külön try-catch-finally szerkezeteket, mert nehezen olvashatóvá tennék a kódot. Helyezzük el inkább az érintett utasításokat egyetlen try blokkban, és készítsünk minden kivétel típushoz catch blokkot. .

More Related