1 //
2 // Hogyan kezeljük le a kivételes eseményeket?
3 //
4
5 //
6 // C-stílus
7 //
8
9 struct record { ... };
10
11 record r;
12 extern int errno;
13
14 FILE *fp;
15
16 if ( (fp = fopen( "fname", "r")) != NULL )
17 {
18 fprintf( stderr, "can't open file %s\n", "fname");
19 errno = 1;
20 }
21 else if ( ! fseek( fp, 0L, n*sizeof(r)) )
22 {
23 fprintf( stderr, "can't find record %d\n", n);
24 errno = 2;
25 }
26 else if ( 1 != fread( &r, sizeof(r), 1, fp) )
27 {
28 fprintf( stderr, "can't read record\n");
29 errno = 3;
30 }
31 else ...
32
33
34 //
35 // assert
36 //
37
38 #include <cassert>
39
40 int main()
41 {
42 ...
43 assert( ptr != 0 );
44 ...
45 }
46
47
48 //
49 // setjmp/longjmp a C nyelvben
50 //
51
52 #include <setjmp.h>
53 #include <stdio.h>
54
55 jmp_buf x; // globális változó, vagy paraméterként át kell adni
56
57 // ez a függvény fog kivételt kiváltani
58 void f()
59 {
60 if ( ...hibát észlelünk... )
61 longjmp(x,5); // kiváltja a kivételt
62 }
63
64 int main()
65 {
66 int i = 0;
67
68 // setjmp elsőre 0-val tér vissza
69 // másodszorra a longjmp() paraméterével
70 if ( (i = setjmp(x)) == 0 )
71 {
72 // első alkalommal ide jutunk
73 f();
74 }
75 else
76 {
77 // a kivétel esetén jutunk ide
78 switch( i )
79 {
80 case 1: /* lekezeljük a hibát */
81 case 2: /* lekezeljük a másik hibát */
82 default: fprintf( stdout, "error code = %d\n", i); break;
83 }
84 }
85 return 0;
86 }
87
88
89 A kivételkezelés célja
90
91 - vezérlésátadás a hiba detektálásának helyéről (a cél ismeretlen)
92 - tetszőleges adat továbbítása típusbiztosan a handlerhez
93 - minden kivételt a megfelelő handler kapjon el
94 - a kivételek legyenek csoportosíthatóak
95 - működjön helyesen többszálas, párhuzamos környezetben
96
97 - ha nem váltunk ki kivételt, akkor ne legyen kód/futásiidő költség
98 - működjön együtt más nyelvekkel, és az operációs rendszerrel
99
100
101
102 A kivételkezelés összetevői:
103
104 - try block
105 - catch handlers
106 - throw expression
107
108
109 try
110 {
111 // ez a felügyelt kódrészlet
112 f();
113 }
114 catch (T1 e1) { /* handler T1 típusra */ }
115 catch (T2 e2) { /* handler T2 típusra */ }
116 catch (T3 e3) { /* handler T3 típusra */ }
117 // ha nem volt kivétel, itt folytatódik
118
119
120 void f()
121 {
122 //...
123 T e;
124 throw e; /* T típusú e objektumot dob */
125
126 // vagy:
127 throw T(); /* a T típusú default értéket dobja */
128 }
129
130
131 Egy H típusú handler akkor kapja el az E típusú kivételt, ha:
132
133 - H és E megegyező típusok
134 - H egyértelmű bázisosztálya E-nek
135 - H és E pointerek vagy referenciák és fennáll 1 vagy 2
136
137
138