Article View: pl.comp.lang.c
Article #267802Re: Ciemna strona C++
From: Sektor van Skijlen
Date: Wed, 05 Dec 2007 13:44
Date: Wed, 05 Dec 2007 13:44
139 lines
8353 bytes
8353 bytes
Dnia Tue, 4 Dec 2007 08:43:18 -0800 (PST), Maciej Sobczak skrobie: > On 3 Gru, 22:50, Sektor van Skijlen > > PS. Swoją drogą, zauważyłem że na wszystkich tutorialach - nie sprawdzałem > > dokładnie swojego pod tym względem, ale chyba jest chlubnym wyjątkiem :) - > > całkowicie ŹLE tłumaczą, jak wygląda obsługa nieoczekiwanego wyjątku i wyjątku > > poprzez main(), czyli sprawa unexpected() i terminate(). > > > > Funkcje set_terminate() i set_unexpected() nie służą do ustawiania własnych > > handlerów wykonujących się ZAMIAST domyślnych (to nie jest "szklanka zimnej > > wody jako środek antykoncepcyjny"). Handlery te wykonują się PRZED domyślną > > obsługą. > [...] > Nie. > Funkcje podane przez użytkownika są ZAMIAST a nie PRZED. > set_terminate() ustawia funkcję, wobec której standard wymaga, aby > zakończyła program. Nie ma sensu rozważać, co się dzieje potem. Gdzie tak przepraszam wyczytałeś, bo ja niczego takiego w standardzie nie widzę (wsiąkł mi gdzieś ISO C++ 2002, mam tylko draft na C++0x, ale tam się chyba nic nie zmieniło, a przynajmniej wątpię, żeby na gorsze). O funkcji terminate jest napisane dokładnie tyle, cytuję (18.6.3.3): void terminate (); 1 Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1). May also be called directly by the program. 2 Effects: Calls the terminate_handler function in effect immediately after evaluating the throw-expression (18.6.3.1), if called by the implementation, or calls the current terminate_handler function, if called by the program. Przy set_terminate() też nic na ten temat nie ma: 18.6.3.2 set_terminate [lib.set.terminate] terminate_handler set_terminate ( terminate_handler f ) throw (); 1 Effects: Establishes the function designated by f as the current handler function for terminating exception processing. 2 Requires: f shall not be a null pointer. 3 Returns: The previous terminate_handler . > set_unexpected() ustawia funkcję, wobec której standard wymaga, aby > nie wracała i dodatkowo nakłada reguły (15.5.2/2), które reagują na > jej wyjątki - ale standardowa funkcja nie jest już wołana. Punkt, który podałeś, dotyczy unexpected(), a nie terminate(). Zresztą z całego 15.5.2 wynika dla mnie, że : - unexpected() woła funkcję użytkownika, która może rzucić wyjątkiem (domyślnie sama rzuca std::bad_exception) - jeśli funkcja ma specyfikację wyjątków i nie wypuszcza typu tego wyjątku, rzucany jest wyjątek std::bad_exception. Jeśli tego wyjątku funkcja również nie wypuszcza, wywoływane jest terminate() Niestety z tego opisu nie wynika dla mnie jasno, co się stanie, jeśli użytkownika handler unexpected() nie zrobi nic. Z tego, co przypuszczam, opis sugeruje, że jeśli nie zrobi nic, to i tak nastąpi próba rzucenia std::bad_exception. Nie jestem jednak o tym aż tak przekonany, bo do powodów, przy których woła się std::terminate() należy (15.5.1/1): - when the implementation's default unexpected exception handler is called (18.6.2.2) Czyli jeśli jest wołany jakiś nie-default, to terminate jest "niekoniecznie wołana"? Nie ma nigdzie w standardzie takiego zastrzeżenia, że terminate() ma nie wracać. Co więcej, decyzję, czy zwijać stos gdy terminate() jest wynikiem wyskoczenia wyjątku z main() [użyłem skrótu myślowego] pozostawia implementacji - może więc i implementacja decyduje, czy z terminate() można wracać, czy nie. Wyrażenie "shall not return" jest użyte tylko w stosunku do unexpected(): 18.6.2.2 Type unexpected_handler [lib.unexpected.handler] typedef void (* unexpected_handler )(); 1 The type of a handler function to be called by unexpected() when a function attempts to throw an exception not listed in its exception-specification. 2 Required behavior: An unexpected_handler shall not return. See also 15.5.2. 3 Default behavior: The implementation.s default unexpected_handler calls terminate(). ... 18.6.3.1 Type terminate_handler [lib.terminate.handler] typedef void (* terminate_handler )(); 1 The type of a handler function to be called by terminate() when terminating exception processing. 2 Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller. 3 Default behavior: The implementation.s default terminate_handler calls abort(). Czy na podstawie standardu jesteś więc w stanie określić, czy: - wolno nie kończyć programu w terminate() - implementacji wolno utłuc program abort()-em jeśli użytkownik nie ubije wcześniej programu w swoim handlerze terminate()? > Nie ma tu żadnego PRZED. To jest ZAMIAST. Po raz kolejny wytłumaczę się w ten sposób: może i standard nie wyraża się wprost, że jest to PRZED, tylko mówi, że niby ZAMIAST, ale i tak musisz zakończyć program. Ale takie tłumaczenie jest niepotrzebnie zbyt skomplikowane, a praktyka jest po prostu prostsza. Nie przyglądałem się, jak to jest w standardzie - o tym, że oryginalna terminate() i tak jest wołana po funkcji użytkownika, przeczytałem w DEC++. Nie wiem, na ile jest to sprawa implementacji, ale jedynym sposobem wymuszenia na użytkowniku, żeby w swoim handlerze spowodował zakończenie programu jest spowodowanie zakończenia programu po jej zakończeniu. Ponieważ w domyślnej sytuacji nic innego nie robi (a kończy program i tak w ten sam sposób), więc metodą logicznej eliminacji jedyną sensowną implementacją spełniającą wymogi standardu jest wywołać abort() zaraz po wykonaniu funkcji użytkownika - najwyżej użytkownik zakończy program poprzez exit() zanim do tego dojdzie. Nie ma jednak, niestety, sposobu na to, żeby uniemożliwić użytkownikowi odkładanie tego zakończenia ad calendas graecas. W tym wypadku jednak nie starałbym się aż tak narzucać użytkownikowi czegokolwiek, bo jeśli usiłuje kontynuować pracę już zepsutej aplikacji, to jego problem. Ale nawet zakładając, że tak rzecze standard, nie zmienia to faktu: większość tutoriali twierdzi stanowczo, że funkcja ta używana jest ZAMIAST oryginalnego handlera, "trochę zapominając" wspomnieć, że funkcja ta MUSI spowodować również zakończenie programu -- // _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl> \\ L_ |/ `| /^\ ,() <ethouris(O)gmail.com> // \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx "Java is answer for a question that has never been stated"
Technical Details
Message-ID:
<fj69vc$te$1@kujawiak.man.lodz.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mailReferences:
<fghgeo$spf$1@nemesis.news.tpi.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <1195688300.8426.30.camel@qrnik> <fi3ems$7ig$1@kujawiak.man.lodz.pl> <1195734091.8426.77.camel@qrnik> <fi6n5f$fpr$1@kujawiak.man.lodz.pl> <1195858230.20523.107.camel@qrnik> <fie2un$cbn$1@kujawiak.man.lodz.pl> <1196076390.30869.52.camel@qrnik> <fj1tmo$52u$1@kujawiak.man.lodz.pl> <1101d6ea-b312-4214-b153-8e1cc26a99ba@n20g2000hsh.googlegroups.com>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mail
From: Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid>
Newsgroups: pl.comp.lang.c
Subject: Re: Ciemna strona C++
Date: Wed, 5 Dec 2007 13:44:12 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 139
Sender: Michal Malecki <sektor@student.kis.p.lodz.pl>
Message-ID: <fj69vc$te$1@kujawiak.man.lodz.pl>
References: <fghgeo$spf$1@nemesis.news.tpi.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <1195688300.8426.30.camel@qrnik> <fi3ems$7ig$1@kujawiak.man.lodz.pl> <1195734091.8426.77.camel@qrnik> <fi6n5f$fpr$1@kujawiak.man.lodz.pl> <1195858230.20523.107.camel@qrnik> <fie2un$cbn$1@kujawiak.man.lodz.pl> <1196076390.30869.52.camel@qrnik> <fj1tmo$52u$1@kujawiak.man.lodz.pl> <1101d6ea-b312-4214-b153-8e1cc26a99ba@n20g2000hsh.googlegroups.com>
NNTP-Posting-Host: student.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1196862252 942 212.191.89.21 (5 Dec 2007 13:44:12 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Wed, 5 Dec 2007 13:44:12 +0000 (UTC)
User-Agent: tin/1.8.3-20070201 ("Scotasay") (UNIX) (FreeBSD/6.2-RELEASE-p3 (sparc64))
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit