Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Exception specification

[es] :: C/C++ programiranje :: Exception specification

[ Pregleda: 2932 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
*.eunet.rs.



+171 Profil

icon Exception specification21.10.2008. u 22:23 - pre 188 meseci
Pozdrav

Zadnjih dana gledam C++-ov exception handling mehanizam. Moram priznati da sam tek od skora upoznat sa exception specification, i licno, deluje mi logicno i veoma dobro osmisljeno, no na raznim mestima sam naleto da je to osudjeno na propast i da se malo koristi. Da li je ovo istina, koliko vi koristite u svojim programima exception specification i sta mislite o istom?
 
Odgovor na temu

deerbeer
Beograd

Član broj: 174418
Poruke: 1189
*.adsl-a-1.sezampro.yu.



+395 Profil

icon Re: Exception specification21.10.2008. u 23:23 - pre 188 meseci
Ajd malo pojasni : SEH , std::exception, boost , mFC or what ?

Viva lollapalooza
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Exception specification22.10.2008. u 00:31 - pre 188 meseci
Mislim da je čovek mislio na C++ izuzetke.

U principu, nemoj da koristiš specifikaciju izuzetaka (barem ne u konačnoj verziji softvera).

Ako i pored toga želiš da koristiš speficikaciju, obrati pažnju na sledeće:

1) Kao prvo, neki kompajleri ne poštuju Standard kada su u pitanju izuzeci. Recimo, GCC poštuje Std, dok VC++ ne poštuje (ako u VC++-u navedeš specifikaciju, on je ignoriše, sem ako je to nothrow specifikacija) A i možeš da dobiješ neke lude rezultate ako kompajler vrši neku (validnu) optimizaciju na osnovu speficikacije, a ipak se desi neželjeni izuzetak. Onda ćeš poželeti da je nije vršio :)

2) Vodi računa o tome da se specifikacija izuzetaka tretira kao relevantan deo potpisa funkcije

Prost primer:
Code:

class A
{
  virtual void f() throw(E1);
};

class B : public A
{
  virtual void f() throw(E2);
};


Ovde bi E1 i E2 trebalo da budu kovarijantni, odnosno da E2 nasleđuje E1. I sada se recimo desi da promeniš specifikaciju u klasi A, moraš da menjaš shodno tome i u B. A to je užas...mislim, teško.

3) Bacanje izuzetka koji se ne nalazi u specifikaciji vodi ka garantovanom prekidu programa, jer se zove unexpected() (makar je i redefinisao, malo šta možeš da uradiš iz nje).


Eventualno vredi korišćenje nothrow specifikacije jer je tu situacija jasna. Ali je bolje da ipak ne koristiš ništa od toga u završnoj verziji kako te ne bi bolela glava.
 
Odgovor na temu

kiklop74
Darko Miletić
Buenos Aires

Član broj: 78422
Poruke: 569
*.fibertel.com.ar.

Sajt: ar.linkedin.com/pub/darko..


+13 Profil

icon Re: Exception specification22.10.2008. u 01:59 - pre 188 meseci
Herb Sutter u svojoj odlicnoj knjizi "Exceptional C++" daje detaljno objasnjenje exepction specifikacija i u zakljucku kaze:

Citat:

Moral #1: Never write an exception specification.
Moral #2: Except possibly an empty one, but if I were you, I'd avoid even that.


Evo dela objasnjenja:

Citat:
Issue the Second: (Mis)understandings

The second issue has to do with knowing what you're getting. As many notable persons, including the authors of the Boost exception specification rationale [BoostES], have put it, programmers tend to use exception specifications as though they be-haved the way the programmer would like, instead of the way they actually do be-have.

Hence the question:

4.What are exception specifications, and what do they do? Be precise.

Here's what many people think exception specifications do:

*Guarantee that functions will throw only listed exceptions (possibly none).
*Enable compiler optimizations based on the knowledge that only listed exceptions (possibly none) will be thrown.

These expectations are, again, deceptively close to being correct. Consider again the code in Example 13-2(b):

Code:

// Example 13-2(b) reprise, and two potential white lies:
//
int Gunc() throw();           // will throw nothing   ?

int Hunc() throw(A,B);        // can only throw A or B ?


Are the comments correct? Not quite. Gunc might indeed throw something, and Hunc might well throw something other than A or B! The compiler just guarantees to beat them senseless if they do… oh, and to beat your program senseless too, most of the time.

Because Gunc or Hunc could indeed throw something they promised not to, not only can't the compiler assume it won't happen, but the compiler is also responsible for being the policeman with the billy club who checks to make sure such a bad thing doesn't happen undetected. If it does happen, then the compiler must invoke the unexpected function. Most of the time, that will terminate your program. Why? Because there are only two ways out of unexpected, neither of which is a normal return. You can pick your poison:

*Throw instead an exception that the exception specification does allow. If so, the exception propagation continues as it would normally have. But remember that the unexpected handler is global—there is only one for the whole program. A global handler is highly unlikely to be smart enough to Do the Right Thing for any given particular case, and the result is to go to terminate, go directly to terminate, do not pass catch, do not collect $200.
*Throw instead (or rethrow) an exception that the exception specification (still) doesn't allow. If the original function allowed a bad_exception type in its exception specification, okay, then it's a bad_exception that will now get propagated. But if not, then go to terminate, go directly to terminate…

Because violated exception specifications end up terminating your program the vast majority of the time, I think it's legitimate to call that "beating your program senseless."

Earlier, we saw two bullets stating what many people think that exception specifications do. Here is an edited statement that more accurately portrays what they actually do do [sic]:[19]

[19] Yes, this is a sic joke.

*Guarantee Enforce at run-time that functions will throw only listed exceptions (possibly none).
*Enable or prevent compiler optimizations based on the knowledge that only listed exceptions (possibly none) will be thrown having to check whether listed exceptions are indeed being thrown.

To see what a compiler has to do, consider the following code, which provides a body for one of our sample functions, Hunc:

Code:

// Example 13-4(a)
//
int Hunc() throw(A,B) {
 return Junc();
}


Functionally, the compiler must generate code like the following, and it's typically just as costly at run-time as if you'd hand-written it yourself (though less typing because the compiler generates it for you):
Code View: Scroll / Show All

Code:

// Example 13-4(b): A compiler's massaged version of Example 13-4(a)
//
int Hunc()
try {
 return Junc();
}
catch(A) {
 throw;
}
catch(B) {
 throw;
}
catch(…) {
 std::unexpected();  // won't return! but might throw an A or a B if you're lucky
}



Here we can see more clearly why, rather than letting the compiler make optimizations by assuming only certain exceptions will be thrown, it's exactly the reverse: The compiler has to do more work to enforce at run-time that only those exceptions are indeed thrown.

Tko leti vrijedi
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p1-7.bvcom.net.



+1064 Profil

icon Re: Exception specification22.10.2008. u 06:33 - pre 188 meseci
Moram da dodam jednu stvar koju je Herb propustio ;)

Svojevremeno sam gledao kako g++ implementira exception-e i empty specifikacija
moze da se koristi da bi se izbegao run time ili space overhead.
Evo kako.

Recimo:

void g()throw();

void f()throw()
{
A a; // a destruktor je vidljiv ili ima empty spec
// i ne poziva f-je koje nemaju empty spec ili im se vidi definicija a ne bacaju exc
g();
}

ukoliko g *ne bi imao empty spec* kompajler bi morao da registruje handler svaki put
kad udje u f-ju f i da deregistruje kad izlazi, ili da permanentno drzi u tabeli eh-ra.

dakle *da g nema empty spec* to bi bilo ekvivalentno
void f()throw()
try
{
A a;
g();
}
catch(...)
{
a.~A();
unexpected(); // ili throw; ukoliko f nema spec
}

Dakle empty spec se koristi da bi izbacili overhead exception handlinga kad se ne koristi.
Jos jedna stvar, bez obzira sto *f ima specifikaciju* nikakav kod nece biti generisan zato sto
kompajler vidi da tu nista ne moze da izbaci exception niti g (zbog specifikacije) niti A.

E sad da li zarad run time ili space overheada treba da pisemo empty specifikacije
kad ne koristimo exceptione?
Programeri drugih jezika pristaju na mnogo teze run time i space overhead-e a ovo i nije nesto ;)
Recimo operator new i delete imaju nothrow specifikaciju bas iz tih razloga.

Pozdrav!


[Ovu poruku je menjao Branimir Maksimovic dana 22.10.2008. u 07:45 GMT+1]
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Exception specification22.10.2008. u 08:57 - pre 188 meseci
@deerbeer
Mislim bas na exception specification, mada to se vec vidi iz Branimirovog i kiklop74-ovog posta.

Citirao bi Herb-a

Citat:

Guarantee Enforce at run-time that functions will throw only listed exceptions (possibly none).
Enable or prevent compiler optimizations based on the knowledge that only listed exceptions (possibly none) will be thrown having to check whether listed exceptions are indeed being thrown.


Koliko sam uspeo da shvatim po njemu ovo gore nije ispravno jer ono sto pise u deklaraciji f-je u runtime-u moze da bude a i ne mora, tj. f-ja moze da baci exception za koji nema specifikaciju (ne nalazi se u deklaraciji), po meni ovo jeste dobro, jer ako onaj ko poziva f-ju dobija nesto drugo od onoga za sta f-ja ima potpis, onda sve sto moze da se uradi je da ze pozove unexpected(). Jel onaj ko je pozvao f-ju ionako ne zna (u to sam siguran 99% ili bar u tolikoj meri slucajeva se to desava...) sta da radi sa tim "nedefinisanim" exception-om.

I jos nesto sto je Herb spomenuo
Citat:

exception specifications can cost you programmer time because they increase coupling

Ovaj deo mi i nije jasan. Ako neko menja neku f-ju u nekoj base klasi i menja joj exception specifikaciju tako da ona zahteva menjanje u svim derived klasama onda po Herbu se povecava "coupling". Ali zar to nije isto kao kad neko odluci da prosiri f-ju sa dodatnim parametrom?
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p1-7.bvcom.net.



+1064 Profil

icon Re: Exception specification22.10.2008. u 10:34 - pre 188 meseci
Nisi bas najjasniji ;)

F-ja ne moze baciti exception van specifikacije. unexpected f-ja prvo zove unex handler pa terminate.
unex handler sluzi da prepravis exception ako se iz nje izadje onda se posle toga zove terminate();
koji sluzi da odradis cleanup i onda ide abort();

na pr:
Code:

#include <iostream>
#include <exception>
using namespace std;

typedef void (*ft)();

void my_terminate() {
// cleanup panic 
  cout << "Call to my terminate" << endl;
}

void my_unexpected() {
  cout << "Call to my_unexpected()" << endl;
  throw; // convert exception to bad_exception or some other
  // eg throw MyBadException;
}

struct A{};

void f() throw(A,bad_exception) {
  throw int();
}

int main()
{
  ft old_term = set_terminate(my_terminate);
  ft old_unex = set_unexpected(my_unexpected);
  try {
    cout << "In first try block" << endl;
    f();
  }
  catch (bad_exception& e) {
    cout << "Caught bad_exception" << endl;
  }
  catch (...) {
    cout << "Caught some exception" << endl;
  }

  cout << endl;

  set_unexpected(old_unex);
  try {
    cout << "In second try block" << endl;
    f();
  }
  catch (bad_exception& e) {
    cout << "Caught bad_exception" << endl;
  }
  catch (...) {
    cout << "Caught some exception" << endl;
  }
}



No ta gimnastika sa bad_exception i specifikacijama uopste nije neophodna posto
to isto jednostavno mozes da uradis sa catch(...) a ovo zahteva vremena
i razmisljanja

Pozdrav!

 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Exception specification22.10.2008. u 10:44 - pre 188 meseci
Hvala na odgovoru.

Posto sam sad na poslu pogledacu ovo kasnije pa cemo nastaviti.
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.dynamic.sbb.rs.



+9 Profil

icon Re: Exception specification22.10.2008. u 15:56 - pre 188 meseci
@Branimir

Pitanje je koliko je ta optimizacija dobra, zato što navođenje nothrow specifikacije ne znači da f-ja g() (ili neki podpoziv) neće da proizvede izuzetak... a ako proizvede, eto memory leak-a (u ovom slučaju). Znači, ta specifikacija služi da bi te unexpteced() "lupila po glavi" ako se desi nešto što nisi direktno predvideo i da se nepredviđeni bačeni izuzetak ne bi slučajno popeo naviše i napravio ti zbrku da ne znaš gde je nastala greška.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p1-7.bvcom.net.



+1064 Profil

icon Re: Exception specification22.10.2008. u 20:11 - pre 188 meseci
Nisi bas najjasniji u ovom slucaju. Na kakav memory leak mislis? Daj primer?

Drugo empty spec jeste optimizacija i treba da se koristi onda kad si siguran da nece biti exceptiona,
inace koja je poenta? Da ti program puca sa abort()?

Hocu da kazem, da ako pozivas f-ju sa nothrow specifikacijom slobodno isto mozes
da stavis nothrow.

Pozdrav!
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Exception specification24.10.2008. u 13:17 - pre 188 meseci
@Branimir
Koji kompajler koristis?

Citat:

F-ja ne moze baciti exception van specifikacije. unexpected f-ja prvo zove unex handler pa terminate.
unex handler sluzi da prepravis exception ako se iz nje izadje onda se posle toga zove terminate();
koji sluzi da odradis cleanup i onda ide abort();


Za ovo si u pravu i nisi
Tvoja funkcija f() baca int, u specifikaciji pise da baca A i bad_exception, mada kada je u pitanju ES onda si u pravu jer pretpostavljam da ce to kompajler da zavrapuje u jedan cath(...) koji ce da uhvati sve sto ne odgovara specifikaciji.

Citat:

No ta gimnastika sa bad_exception i specifikacijama uopste nije neophodna posto
to isto jednostavno mozes da uradis sa catch(...) a ovo zahteva vremena i razmisljanja


Ovo ne razumem, kako mislis da moze da se uradi sa catch(...)? Ako se uradi sa catch(...) onda se gubi i smisao ES-a, mada znam to i jeste tvoja poenta ali zasto bi neko hvatao catch(...) exception-e? Zar kada se dodje do tog nivo da f-ja hvata catch(...) ne dolazi upravo do toga da jedino sto moze da se uradi da se ugasi aplikacija?
Koliko ja vidim ES mi omogucava da mogu da koristim 3rd party biblioteke a da ne moram da razmisljam o tome sta ce metod da baci, tj. da trazim kako bi handlovao samo njegove exceptione a ne general exception. U stvari nisu to samo 3rd party biblioteke (f-je) nego i sve f-je koje koristim u programu a da ne moram da idem da gledam kako je implementirana f-ja, nekako mi deluje eksplicitnije i jasnije sa ES-ima.
Inace ja radim u .NET-u, dok C++ koristim samo na poslu (sto me teraju ), pa nisam mozda najbolje upoznat sa exceptionima u C++, ali kada sam saznao za ES u C++, prvo mi je palo napamet zasto ne postoji i u C#-u, i moram priznati da odgovor koji sam nasao od Anders Hejlsberg-a deluje pomalo cudno.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
c-bg-d-p6-205.bvcom.net.



+1064 Profil

icon Re: Exception specification24.10.2008. u 16:13 - pre 188 meseci
Koristim g++.

Kada kazem da u c++ f-ja ne moze da baci exception van specifikacije, to znaci da ne moze ;)
Tj exception van specifikacije ne moze napustiti datu f-ju u run time-u. Naravno
to ne znaci da ce ti kompajler javiti gresku ako tako nesto pokusas u compile time-u.

Excpetion specifikacije nemaju puno smisla bas kad koristis third party libove.
Oni zahtevaju disciplinu upravo zato sto je to run time mehanizam.
Tesko da mozes u nekom slucaju bas predvideti tacno koji ce sve exceptioni
izletati iz f-ja ukoliko ispod toga stoji hijerahrija poziva. To povecava zavisnost
izmedju koda i moras bas da pazis da negde ne opalis throw koji ce izavati
krah programa.
No svaki nepredvidjeni exception se moze uhvatiti sa catch(...) i ako zaista ima potrebe
tu i zaustaviti program. Ne vidim uopste svrhu run time enforsiranja, kao ni mnogi drugi ;)

Pozdrav!
 
Odgovor na temu

[es] :: C/C++ programiranje :: Exception specification

[ Pregleda: 2932 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.