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