Exception handling (programming): Difference between revisions

Content deleted Content added
OAbot (talk | contribs)
m Open access bot: doi added to citation with #oabot.
Line 93:
The implementation of exception handling in programming languages typically involves a fair amount of support from both a code generator and the [[runtime system]] accompanying a compiler. (It was the addition of exception handling to C++ that ended the useful lifetime of the original C++ compiler, [[Cfront]].<ref>[[Scott Meyers]], [http://www.artima.com/cppsource/top_cpp_software.html The Most Important C++ Software...Ever] {{webarchive|url=https://web.archive.org/web/20110428221802/http://www.artima.com/cppsource/top_cpp_software.html |date=2011-04-28 }}, 2006</ref>) Two schemes are most common. The first, ''{{visible anchor|dynamic registration}}'', generates code that continually updates structures about the program state in terms of exception handling.<ref>D. Cameron, P. Faust, D. Lenkov, M. Mehta, "A portable implementation of C++ exception handling", ''Proceedings of the C++ Conference'' (August 1992) [[USENIX]].</ref> Typically, this adds a new element to the [[Call stack|stack frame layout]] that knows what handlers are available for the function or method associated with that frame; if an exception is thrown, a pointer in the layout directs the runtime to the appropriate handler code. This approach is compact in terms of space, but adds execution overhead on frame entry and exit. It was commonly used in many Ada implementations, for example, where complex generation and runtime support was already needed for many other language features. Microsoft's 32-bit [[Structured Exception Handling]] (SEH) uses this approach with a separate exception stack.<ref>{{cite web|url=http://stoned-vienna.com/html/index.php?page=windows-exception-handling|author=Peter Kleissner|title=Windows Exception Handling - Peter Kleissner|date=February 14, 2009|access-date=2009-11-21 |archive-url=https://web.archive.org/web/20131014204335/http://stoned-vienna.com/html/index.php?page=windows-exception-handling |archive-date=October 14, 2013 |url-status=dead}}, ''Compiler based Structured Exception Handling'' section</ref> Dynamic registration, being fairly straightforward to define, is amenable to [[proof of correctness]].<ref>Graham Hutton, Joel Wright, "[http://www.cs.nott.ac.uk/~gmh/exceptions.pdf Compiling Exceptions Correctly] {{webarchive|url=https://web.archive.org/web/20140911173720/http://www.cs.nott.ac.uk/~gmh/exceptions.pdf |date=2014-09-11 }}". ''Proceedings of the 7th International Conference on Mathematics of Program Construction'', 2004.</ref>
 
The second scheme, and the one implemented in many production-quality C++ compilers and 64-bit Microsoft [[Structured Exception Handling|SEH]], is a {{visible anchor|table-driven approach|text=''table-driven'' approach}}. This creates static tables at [[compile time]] and [[link time]] that relate ranges of the [[program counter]] to the program state with respect to exception handling.<ref>{{cite journal | title=Exception handling – Supporting the runtime mechanism | last=Lajoie | first= Josée | journal=C++ Report | volume=6 | issue=3 | date=March–April 1994}}</ref> Then, if an exception is thrown, the runtime system looks up the current instruction ___location in the tables and determines what handlers are in play and what needs to be done. This approach minimizes executive overhead for the case where an exception is not thrown. This happens at the cost of some space, but this space can be allocated into read-only, special-purpose data sections that are not loaded or relocated until an exception is actually thrown.<ref name=cppeh>{{cite journal | title=Optimizing away C++ exception handling | last=Schilling | first=Jonathan L. | journal=[[SIGPLAN Notices]] | volume=33 | issue=8 | date=August 1998 | pages=40–47 | doi=10.1145/286385.286390| s2cid=1522664 | doi-access=free }}</ref> The ___location (in memory) of the code for handling an exception need not be located within (or even near) the region of memory where the rest of the function's code is stored. So if an exception is thrown then a performance hit – roughly comparable to a function call<ref name=MiscrosoftDocsExceptions>{{cite web|title=Modern C++ best practices for exceptions and error handling|work=Microsoft|date=8 March 2021|access-date=21 March 2022|url=https://docs.microsoft.com/en-us/cpp/cpp/errors-and-exception-handling-modern-cpp}}</ref> – may occur if the necessary exception handling code needs to be loaded/cached. However, this scheme has minimal performance cost if no exception is thrown. Since exceptions in C++ are supposed to be ''exceptional'' (i.e. uncommon/rare) events, the phrase "zero-cost exceptions"<ref group=note>There is "zero [processing] cost" only if no exception is throw (although there will be a memory cost since memory is needed for the lookup table). There is a (potentially significant) cost if an exception is thrown (that is, if <code>throw</code> is executed). Implementing exception handling may also limit the possible [[Optimizing compiler|compiler optimizations]] that may be performed.</ref> is sometimes used to describe exception handling in C++. Like [[runtime type identification]] (RTTI), exceptions might not adhere to C++'s [https://en.cppreference.com/w/cpp/language/Zero-overhead_principle zero-overhead principle] as implementing exception handling at run-time requires a non-zero amount of memory for the lookup table.<ref name=StroustrupExceptions2019>{{cite web|last=Stroustrup|first=Bjarne|author-link=Bjarne Stroustrup|title=C++ exceptions and alternatives|date=18 November 2019|access-date=23 March 2022|url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1947r0.pdf}}</ref> For this reason, exception handling (and RTTI) can be disabled in many C++ compilers, which may be useful for systems with very limited memory<ref name=StroustrupExceptions2019 /> (such as [[embedded system]]s). This second approach is also superior in terms of achieving [[thread safety]]{{Citation needed|date=September 2012}}.
 
Other definitional and implementation schemes have been proposed as well. For languages that support [[metaprogramming]], approaches that involve no overhead at all (beyond the already present support for [[reflection (computer science)|reflection]]) have been advanced.<ref>M. Hof, H. Mössenböck, P. Pirkelbauer, "[http://www.ssw.uni-linz.ac.at/Research/Papers/Hof97b.html Zero-Overhead Exception Handling Using Metaprogramming] {{webarchive|url=https://web.archive.org/web/20160303180327/http://www.ssw.uni-linz.ac.at/Research/Papers/Hof97b.html |date=2016-03-03 }}", ''Proceedings SOFSEM'97'', November 1997, ''Lecture Notes in Computer Science 1338'', pp. 423-431.</ref>