Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

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

Hasonló előadás


Az előadások a következő témára: "1 KIVÉTELKEZELÉS Programozási nyelvek összehasonlító elemzése Készítette: Pásztor Attila KF GAMF ELTE-IK DOKTORI ISKOLA PHD hallgató."— Előadás másolata:

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

2 2 KIVÉTELKEZELÉS  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 Tartalom:

3 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 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 5 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. –az operációs rendszerben meglévő programozói hibák.  Hardverhibák –elromlott winchester miatti leállások, –elfogy a memória, stb. Kivétel : olyan futás közben fellépő hiba ami megszakítja az utasítások normál futási sorrendjét

6 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 7 ”Kivételkezelés” a C nyelvben int FGV() { 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 8 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; } ”Kivételkezelés” a C nyelvben - hibakezelés helyben

10 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) 110format(’Hiba’)

11 11 1. Aritmetikai műveletek hibáinak kezelése 2. Input –output műveletek közbeni hibák kezelése Kivételkezelés kezdetei - COBOL 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 12  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 Kivételkezelés kezdetei – PL/I

13 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 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 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 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 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 18 Fejlett kivételkezelés :C++ try { try { // kivétel keletkezhet } catch( típus [név]){ 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 { try { // mindenféle kivétel keletkezhet } catch( ….){ catch( ….){ // minden kivételt elkap }

19 19 Fejlett kivételkezelés :C++ int main() { int main() { FILE *fptr; FILE *fptr; try { try { fptr=fopen("c:\\kw.txt", "r"); fptr=fopen("c:\\kw.txt", "r"); if( fptr ==NULL ) throw "baj van"; if( fptr ==NULL ) throw "baj van"; } catch(int) {cout << "Exception1" ;} catch(int) {cout << "Exception1" ;} catch(float){cout << "Exception2" ;} catch(float){cout << "Exception2" ;} catch(...) {cout << "Exception3" ; } 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 20 Fejlett kivételkezelés :C++ finally hiányának kezelése class File{ private:FILE *f; private:FILE *f; public: public: File(char *filenev) File(char *filenev) { f=fopen(filenev,"r"); } { f=fopen(filenev,"r"); } ~File(){fclose(f); ~File(){fclose(f); cout<<"lezártam";} cout<<"lezártam";} }; }; void Fgv() { File f("c:\\k.txt"); try{}// itt keletkezhet kiv. try{}// itt keletkezhet kiv. catch(...){}// kiv. kez catch(...){}// kiv. kez // a destruktor miatt fájl lezárás mindenképpen // a destruktor miatt fájl lezárás mindenképpen} int main() {Fgv();}

21 21  Lehetőség függvények fejlécében a dobható kivételek részhalmazát megadni throw "(" [type {"," type}] ")" 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_unexpected segítségével szintén meghívása. Ez a set_unexpected segítségével szintén átállítható. átállítható. Fejlett kivételkezelés :C++

22 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 void D() throw() { C(); // ha C bármit kivált, unexpected -t hív throw 7; // unexpected-t hív } throw 7; // unexpected-t hív } Fejlett kivételkezelés :C++

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

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

25 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 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. public class ExExample { void method1() { void method1() { try { try { method2(3); method2(3); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } } void method2(int i) throws Exception{ void method2(int i) throws Exception{ if (i == 0) trow new Exception("illegal argument: 0"); if (i == 0) trow new Exception("illegal argument: 0"); } }} Fejlett kivételkezelés :Java

27 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 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 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 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 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ére finally { // mindig végrehajtódó utasítások catch (Exception e) { // utasítások AnotherException kezelésére finally { // mindig végrehajtódó utasítások } } Fontos a catch ágak sorrendje

32 32 Fejlett kivételkezelés :Java

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

34 34 Fejlett kivételkezelés :C# Példa 1: using System; class ExceptionTestClass { public static void Main() { int x = 0; try { 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()); } } }

35 35 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#

36 36 Példapogram a throw használatára; több catch ág class Program class Program { static void Main(string[] args) { static void Main(string[] args) { string s = "200"; string s = "200"; int a = 0; int a = 0; try try { a = int.Parse(s); { a = int.Parse(s); if (a > 100) throw new Exception("nem lehet nagyobb, mint 100!\n"); if (a > 100) throw new Exception("nem lehet nagyobb, mint 100!\n"); Console.WriteLine(a); Console.WriteLine(a); } catch (FormatException ex) { catch (FormatException ex) { Console.WriteLine(ex.Message); } Console.WriteLine(ex.Message); } catch (Exception exc) { catch (Exception exc) { Console.WriteLine(exc.Message); } Console.WriteLine(exc.Message); } Console.ReadKey(); 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. Fejlett kivételkezelés :C#

37 37 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

38 38 Fejlett kivételkezelés :C#

39 39   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 Fejlett kivételkezelés :C#

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

41 41 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;

42 42 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

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

44 44 Egyebek : migrációs segédprogramok SQL 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

45 45  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 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. A MATLAB nem nyújt lehetőséget sem újrakezdésre, sem ún. final részre. A catch mindent elkap.

46 46 Ö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..


Letölteni ppt "1 KIVÉTELKEZELÉS Programozási nyelvek összehasonlító elemzése Készítette: Pásztor Attila KF GAMF ELTE-IK DOKTORI ISKOLA PHD hallgató."

Hasonló előadás


Google Hirdetések