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

Programozási nyelvek összehasonlító elemzése

Hasonló előadás


Az előadások a következő témára: "Programozási nyelvek összehasonlító elemzése"— Előadás másolata:

1 Programozási nyelvek összehasonlító elemzése
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 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
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 ”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 // 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 Fejlett kivételkezelés :C++
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_unexpected segítségével szintén átállítható.

22 Fejlett kivételkezelés :C++
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 }

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 [ ]; } catch(bad_alloc) cout << "Elfogyott a memória\n"; system("pause"); return 0;

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

25 Fejlett kivételkezelés :Java
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)

26 Fejlett kivételkezelés :Java
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() {                 try {                         method2(3);                 } catch (Exception e) { e.printStackTrace(); }         }                void method2(int i) throws Exception{                if (i == 0) trow new Exception("illegal argument: 0"); } Tehát a method2() kivételt dob, ha a kapott paraméter 0. Ezt a throws záradékban jelzi. Ha nem lenne a throws záradék, akkor a throw utasításnak try blokkban kellene lennie.A method1() hívja a method2()-t. Mivel a method2() deklaráltan dobja az Exception típusú kivételeket, ezért ezt a method1()-nek kezelnie kell. Ennek megfelelően a method2(3); függvényhívás try-blokkon belül szerepel, majd a catch-ágban elkapjuk az Exception típusú kivételeket. Ha nem lenne itt try-catch blokk, akkor a method1()-nek is deklaráltan dobnia kellene a kivételt throws-záradékban, különben fordítási hibát kapnánk. Egyébként ebben az esetben nem dobódik kivétel, így nem fut le a catch blokk. A catch-blokkban a dobott kivétel printStackTrace() metódusát hívjuk meg, ami a konzolra hibakeresés szempontjából hasznos információkat ír ki a hívási láncról.

27 Fejlett kivételkezelés :Java
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

28 Fejlett kivételkezelés :Java
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.

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ére finally { // mindig végrehajtódó utasítások Fontos a catch ágak sorrendje

32 Fejlett kivételkezelés :Java

33 Fejlett kivételkezelés :C#
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();

34 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()); } } }

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

36 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.

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

39 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

40 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); }

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 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 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 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 Egyebek : Matlab Zéróosztás nem ad hibát a =1;
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

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 "Programozási nyelvek összehasonlító elemzése"

Hasonló előadás


Google Hirdetések