using_exceptions.xml revision 1.1
1<sect1 id="manual.intro.using.exceptions" xreflabel="Using Exceptions"> 2<?dbhtml filename="using_exceptions.html"?> 3 4<sect1info> 5 <keywordset> 6 <keyword> 7 C++ 8 </keyword> 9 <keyword> 10 exception 11 </keyword> 12 <keyword> 13 error 14 </keyword> 15 <keyword> 16 exception neutrality 17 </keyword> 18 <keyword> 19 exception safety 20 </keyword> 21 <keyword> 22 exception propagation 23 </keyword> 24 <keyword> 25 -fno-exceptions 26 </keyword> 27 </keywordset> 28</sect1info> 29 30<title>Exceptions</title> 31 32<para> 33The C++ language provides language support for stack unwinding 34with <literal>try</literal> and <literal>catch</literal> blocks and 35the <literal>throw</literal> keyword. 36</para> 37 38<para> 39These are very powerful constructs, and require some thought when 40applied to the standard library in order to yield components that work 41efficiently while cleaning up resources when unexpectedly killed via 42exceptional circumstances. 43</para> 44 45<para> 46Two general topics of discussion follow: 47exception neutrality and exception safety. 48</para> 49 50 51<sect2 id="intro.using.exception.safety" xreflabel="Exception Safety"> 52<title>Exception Safety</title> 53 54 <para> 55 What is exception-safe code? 56 </para> 57 58 <para> 59 Will define this as reasonable and well-defined behavior by classes 60 and functions from the standard library when used by user-defined 61 classes and functions that are themselves exception safe. 62 </para> 63 64 <para> 65 Please note that using exceptions in combination with templates 66 imposes an additional requirement for exception 67 safety. Instantiating types are required to have destructors that 68 do no throw. 69 </para> 70 71 <para> 72 Using the layered approach from Abrahams, can classify library 73 components as providing set levels of safety. These will be called 74 exception guarantees, and can be divided into three categories. 75 </para> 76 77<itemizedlist> 78 79 <listitem> 80 <para> 81 One. Don't throw. 82 </para> 83 <para> 84 As specified in 23.2.1 general container requirements. Applicable 85 to container and string classes. 86 </para> 87 <para> 88 Member 89 functions <function>erase</function>, <function>pop_back</function>, <function>pop_front</function>, <function>swap</function>, <function>clear</function>. And <type>iterator</type> 90 copy constructor and assignment operator. 91 </para> 92 </listitem> 93 94 <listitem> 95 <para> 96 Two. Don't leak resources when exceptions are thrown. This is 97 also referred to as the <quote>basic</quote> exception safety guarantee. 98 </para> 99 100 <para> 101 This applicable throughout the standard library. 102 </para> 103 </listitem> 104 105 <listitem> 106 <para> 107 Three. Commit-or-rollback semantics. This is 108 referred to as <quote>strong</quote> exception safety guarantee. 109 </para> 110 111 <para> 112 As specified in 23.2.1 general container requirements. Applicable 113 to container and string classes. 114 </para> 115 <para> 116 Member functions <function>insert</function> of a single 117 element, <function>push_back</function>, <function>push_front</function>, 118 and <function>rehash</function>. 119 </para> 120 121 </listitem> 122</itemizedlist> 123 124</sect2> 125 126 127<sect2 id="intro.using.exception.propagating" xreflabel="Exceptions Neutrality"> 128<title>Exception Neutrality</title> 129 <para> 130 Simply put, once thrown an exception object should continue in 131 flight unless handled explicitly. In practice, this means 132 propagating exceptions should not be swallowed in 133 gratuitous <literal>catch(...)</literal> blocks. Instead, 134 matching <literal>try</literal> and <literal>catch</literal> 135 blocks should have specific catch handlers and allow un-handed 136 exception objects to propagate. If a 137 terminating <literal>catch(...)</literal> blocks exist then it 138 should end with a <literal>throw</literal> to re-throw the current 139 exception. 140 </para> 141 142 <para> 143 Why do this? 144 </para> 145 146 <para> 147 By allowing exception objects to propagate, a more flexible 148 approach to error handling is made possible (although not 149 required.) Instead of dealing with an error immediately, one can 150 allow the exception to propagate up until sufficient context is 151 available and the choice of exiting or retrying can be made in an 152 informed manner. 153 </para> 154 155 <para> 156 Unfortunately, this tends to be more of a guideline than a strict 157 rule as applied to the standard library. As such, the following is 158 a list of known problem areas where exceptions are not propagated. 159 </para> 160 161<itemizedlist> 162 <listitem> 163 <para> 164 Input/Output 165 </para> 166 <para> 167 The destructor <function>ios_base::Init::~Init()</function> 168 swallows all exceptions from <function>flush</function> called on 169 all open streams at termination. 170 </para> 171 172 <para> 173 All formatted input in <classname>basic_istream</classname> or 174 formatted output in <classname>basic_ostream</classname> can be 175 configured to swallow exceptions 176 when <function>exceptions</function> is set to 177 ignore <type>ios_base::badbit</type>. 178 </para> 179 180 <para> 181 Functions that have been registered 182 with <function>ios_base::register_callback</function> swallow all 183 exceptions when called as part of a callback event. 184 </para> 185 186 <para> 187 When closing the underlying 188 file, <function>basic_filebuf::close</function> will swallow 189 (non-cancellation) exceptions thrown and return <literal>NULL</literal>. 190 </para> 191 </listitem> 192 <listitem> 193 <para> 194 Thread 195 </para> 196 <para> 197 The constructors of <classname>thread</classname> that take a 198 callable function argument swallow all exceptions resulting from 199 executing the function argument. 200 </para> 201 </listitem> 202</itemizedlist> 203 204</sect2> 205 206<sect2 id="intro.using.exception.no" xreflabel="-fno-exceptions"> 207<title>Doing without</title> 208 <para> 209 C++ is a language that strives to be as efficient as is possible 210 in delivering features. As such, considerable care is used by both 211 language implementer and designers to make sure unused features 212 not impose hidden or unexpected costs. The GNU system tries to be 213 as flexible and as configurable as possible. So, it should come as 214 no surprise that GNU C++ provides an optional language extension, 215 spelled <literal>-fno-exceptions</literal>, as a way to excise the 216 implicitly generated magic necessary to 217 support <literal>try</literal> and <literal>catch</literal> blocks 218 and thrown objects. (Language support 219 for <literal>-fno-exceptions</literal> is documented in the GNU 220 GCC <ulink url="http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options">manual</ulink>.) 221 </para> 222 223 <para>Before detailing the library support 224 for <literal>-fno-exceptions</literal>, first a passing note on 225 the things lost when this flag is used: it will break exceptions 226 trying to pass through code compiled 227 with <literal>-fno-exceptions</literal> whether or not that code 228 has any <literal>try</literal> or <literal>catch</literal> 229 constructs. If you might have some code that throws, you shouldn't 230 use <literal>-fno-exceptions</literal>. If you have some code that 231 uses <literal>try</literal> or <literal>catch</literal>, you 232 shouldn't use <literal>-fno-exceptions</literal>. 233 </para> 234 235 <para> 236 And what it to be gained, tinkering in the back alleys with a 237 language like this? Exception handling overhead can be measured 238 in the size of the executable binary, and varies with the 239 capabilities of the underlying operating system and specific 240 configuration of the C++ compiler. On recent hardware with GNU 241 system software of the same age, the combined code and data size 242 overhead for enabling exception handling is around 7%. Of course, 243 if code size is of singular concern than using the appropriate 244 optimizer setting with exception handling enabled 245 (ie, <literal>-Os -fexceptions</literal>) may save up to twice 246 that, and preserve error checking. 247 </para> 248 249 <para> 250 So. Hell bent, we race down the slippery track, knowing the brakes 251 are a little soft and that the right front wheel has a tendency to 252 wobble at speed. Go on: detail the standard library support 253 for <literal>-fno-exceptions</literal>. 254 </para> 255 256 <para> 257 In sum, valid C++ code with exception handling is transformed into 258 a dialect without exception handling. In detailed steps: all use 259 of the C++ 260 keywords <literal>try</literal>, <literal>catch</literal>, 261 and <literal>throw</literal> in the standard library have been 262 permanently replaced with the pre-processor controlled equivalents 263 spelled <literal>__try</literal>, <literal>__catch</literal>, 264 and <literal>__throw_exception_again</literal>. They are defined 265 as follows. 266 </para> 267 268<programlisting> 269#ifdef __EXCEPTIONS 270# define __try try 271# define __catch(X) catch(X) 272# define __throw_exception_again throw 273#else 274# define __try if (true) 275# define __catch(X) if (false) 276# define __throw_exception_again 277#endif 278</programlisting> 279 280<para> 281 In addition, for every object derived from 282 class <classname>exception</classname>, there exists a corresponding 283 function with C language linkage. An example: 284</para> 285 286<programlisting> 287#ifdef __EXCEPTIONS 288 void __throw_bad_exception(void) 289 { throw bad_exception(); } 290#else 291 void __throw_bad_exception(void) 292 { abort(); } 293#endif 294</programlisting> 295 296<para> 297 The last language feature needing to be transformed 298 by <literal>-fno-exceptions</literal> is treatment of exception 299 specifications on member functions. Fortunately, the compiler deals 300 with this by ignoring exception specifications and so no alternate 301 source markup is needed. 302</para> 303 304<para> 305 By using this combination of language re-specification by the 306 compiler, and the pre-processor tricks and the functional 307 indirection layer for thrown exception objects by the library, 308 libstdc++ files can be compiled 309 with <literal>-fno-exceptions</literal>. 310</para> 311 312<para> 313 User code that uses C++ keywords 314 like <literal>throw</literal>, <literal>try</literal>, 315 and <literal>catch</literal> will produce errors even if the user 316 code has included libstdc++ headers and is using constructs 317 like <classname>basic_iostream</classname>. Even though the standard 318 library has been transformed, user code may need modification. User 319 code that attempts or expects to do error checking on standard 320 library components compiled with exception handling disabled should 321 be evaluated and potentially made conditional. 322</para> 323 324<para> 325 Some issues remain with this approach (see bugzilla entry 326 25191). Code paths are not equivalent, in 327 particular <literal>catch</literal> blocks are not evaluated. Also 328 problematic are <literal>throw</literal> expressions expecting a 329 user-defined throw handler. Known problem areas in the standard 330 library include using an instance 331 of <classname>basic_istream</classname> 332 with <function>exceptions</function> set to specific 333 <type>ios_base::iostate</type> conditions, or 334 cascading <literal>catch</literal> blocks that dispatch error 335 handling or recovery efforts based on the type of exception object 336 thrown. 337</para> 338 339<para> 340 Oh, and by the way: none of this hackery is at all 341 special. (Although perhaps well-deserving of a raised eyebrow.) 342 Support continues to evolve and may change in the future. Similar 343 and even additional techniques are used in other C++ libraries and 344 compilers. 345</para> 346 347<para> 348 C++ hackers with a bent for language and control-flow purity have 349 been successfully consoled by grizzled C veterans lamenting the 350 substitution of the C language keyword 351 <literal>const</literal> with the uglified 352 doppelganger <literal>__const</literal>. 353</para> 354 355 356</sect2> 357 358<sect2 id="intro.using.exception.compat"> 359<title>Compatibility</title> 360 361<sect3 id="using.exception.compat.c"> 362<title>With <literal>C</literal></title> 363<para> 364 C language code that is expecting to interoperate with C++ should be 365 compiled with <literal>-fexceptions</literal>. This will make 366 debugging a C language function called as part of C++-induced stack 367 unwinding possible. 368</para> 369 370<para> 371 In particular, unwinding into a frame with no exception handling 372data will cause a runtime abort. If the unwinder runs out of unwind 373info before it finds a handler, <function>std::terminate()</function> 374is called. 375</para> 376 377<para> 378 Please note that most development environments should take care of 379 getting these details right. For GNU systems, all appropriate parts 380 of the GNU C library are already compiled 381 with <literal>-fexceptions</literal>. 382</para> 383 384</sect3> 385 386<sect3 id="using.exception.compat.posix"> 387<title>With <literal>POSIX</literal> thread cancellation</title> 388 389<para> 390 GNU systems re-use some of the exception handling mechanisms to 391 track control flow for <literal>POSIX</literal> thread cancellation. 392</para> 393 394<para> 395 Cancellation points are functions defined by POSIX as worthy of 396 special treatment. The standard library may use some of these 397 functions to implement parts of the ISO C++ standard or depend on 398 them for extensions. 399</para> 400 401<para> 402 Of note: 403</para> 404 405<para> 406 <function>nanosleep</function>, 407 <function>read</function>, <function>write</function>, <function>open</function>, <function>close</function>, 408 and <function>wait</function>. 409</para> 410 411<para> 412 The parts of libstdc++ that use C library functions marked as 413 cancellation points should take pains to be exception neutral. 414 Failing this, <literal>catch</literal> blocks have been augmented to 415 show that the POSIX cancellation object is in flight. 416</para> 417 418<para> 419 This augmentation adds a <literal>catch</literal> block 420 for <classname>__cxxabiv1::__forced_unwind</classname>, which is the 421 object representing the POSIX cancellation object. Like so: 422</para> 423 424<programlisting> 425 catch(const __cxxabiv1::__forced_unwind&) 426 { 427 this->_M_setstate(ios_base::badbit); 428 throw; 429 } 430 catch(...) 431 { this->_M_setstate(ios_base::badbit); } 432</programlisting> 433 434 435</sect3> 436</sect2> 437 438<bibliography id="using.exceptions.biblio"> 439<title>Bibliography</title> 440 441 <biblioentry> 442 <biblioid class="uri"> 443 <ulink url="http://www.opengroup.org/austin/"> 444 <citetitle> 445 System Interface Definitions, Issue 7 (IEEE Std. 1003.1-2008) 446 </citetitle> 447 </ulink> 448 </biblioid> 449 <pagenums> 450 2.9.5 Thread Cancellation 451 </pagenums> 452 <copyright> 453 <year>2008</year> 454 <holder> 455 The Open Group/The Institute of Electrical and Electronics 456 Engineers, Inc. 457 </holder> 458 </copyright> 459 </biblioentry> 460 461 <biblioentry> 462 <biblioid class="uri"> 463 <ulink url="http://www.boost.org/community/error_handling.html"> 464 <citetitle> 465 Error and Exception Handling 466 </citetitle> 467 </ulink> 468 </biblioid> 469 <author> 470 <firstname>David</firstname> 471 <surname>Abrahams </surname> 472 </author> 473 <publisher> 474 <publishername> 475 Boost 476 </publishername> 477 </publisher> 478 </biblioentry> 479 480 481 <biblioentry> 482 <biblioid class="uri"> 483 <ulink url="http://www.boost.org/community/exception_safety.html"> 484 <citetitle> 485 Exception-Safety in Generic Components 486 </citetitle> 487 </ulink> 488 </biblioid> 489 <author> 490 <firstname>David</firstname> 491 <surname>Abrahams</surname> 492 </author> 493 <publisher> 494 <publishername> 495 Boost 496 </publishername> 497 </publisher> 498 </biblioentry> 499 500 <biblioentry> 501 <biblioid class="uri"> 502 <ulink url="www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1077.pdf"> 503 <citetitle> 504 Standard Library Exception Policy 505 </citetitle> 506 </ulink> 507 </biblioid> 508 <author> 509 <firstname>Matt</firstname> 510 <surname>Austern</surname> 511 </author> 512 <publisher> 513 <publishername> 514 WG21 N1077 515 </publishername> 516 </publisher> 517 </biblioentry> 518 519 <biblioentry> 520 <biblioid class="uri"> 521 <ulink url="http://gcc.gnu.org/ml/gcc-patches/2001-03/msg00661.html"> 522 <citetitle> 523 ia64 c++ abi exception handling 524 </citetitle> 525 </ulink> 526 </biblioid> 527 <author> 528 <firstname>Richard</firstname> 529 <surname>Henderson</surname> 530 </author> 531 <publisher> 532 <publishername> 533 GNU 534 </publishername> 535 </publisher> 536 </biblioentry> 537 538 <biblioentry> 539 <biblioid class="uri"> 540 <ulink url="http://www.research.att.com/~bs/3rd_safe.pdf"> 541 <citetitle> 542 Appendix E: Standard-Library Exception Safety 543 </citetitle> 544 </ulink> 545 </biblioid> 546 <author> 547 <firstname>Bjarne</firstname> 548 <surname>Stroustrup</surname> 549 </author> 550 </biblioentry> 551 552 <biblioentry> 553 <title> 554 Exceptional C++ 555 </title> 556 <pagenums> 557 Exception-Safety Issues and Techniques 558 </pagenums> 559 <author> 560 <firstname>Herb</firstname> 561 <surname>Sutter</surname> 562 </author> 563 </biblioentry> 564 565 <biblioentry> 566 <biblioid class="uri"> 567 <ulink url="http://gcc.gnu.org/PR25191"> 568 <citetitle> 569 GCC Bug 25191: exception_defines.h #defines try/catch 570 </citetitle> 571 </ulink> 572 </biblioid> 573 </biblioentry> 574 575</bibliography> 576 577</sect1> 578