Reputation: 24109
I came across the phrase "zero-cost" exception handling a few minutes ago and finally went to go look it up. I had seen the phrase a few times previously in an exceptions vs return codes context. Here's a short description of "zero-cost" and its alternative "setjmp/longjmp".
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gnat_ugn_unw/Exception-Handling-Control.html
GNAT uses two methods for handling exceptions at run-time. The setjmp/longjmp method saves the context when entering a frame with an exception handler. Then when an exception is raised, the context can be restored immediately, without the need for tracing stack frames. This method provides very fast exception propagation, but introduces significant overhead for the use of exception handlers, even if no exception is raised.
The other approach is called “zero cost” exception handling. With this method, the compiler builds static tables to describe the exception ranges. No dynamic code is required when entering a frame containing an exception handler. When an exception is raised, the tables are used to control a back trace of the subprogram invocation stack to locate the required exception handler. This method has considerably poorer performance for the propagation of exceptions, but there is no overhead for exception handlers if no exception is raised.
(GNAT is an Ada compiler but I'm guessing the explanation above is language-agnostic.)
This helps to explain why we have try
in the first place -- some strategies for handling exceptions require saving context upon entering the try block.
The zero-cost strategy sounds very similar to goto-style cleanup and of course we don't need mightgoto
blocks. Do try
blocks benefit the zero-cost strategy at all? For compilers using this strategy to implement C++ exceptions, would it make any difference if the language allowed naked throw Exception();
statements? Is try
just a form of comment for modern compilers?
Depending on how you build the tables, the cost of zero-cost could depend on the number and location of catch blocks but not on the number and location of try blocks.
Soapbox: The name "zero-cost" is absurdly misleading. Why not just call it "free-lunch"?
Relevant:
Why is `try` an explicit keyword?
Upvotes: 1
Views: 353
Reputation: 254691
Are
try
blocks necessary or even helpful for the “zero-cost” stack unwinding strategy?
Yes, try
blocks are necessary whatever the details of the unwinding strategy. When an exception is thrown, the exception mechanism needs to identify the most recently entered try
block in order to find the associated handlers for that block.
With a "zero-cost" strategy, the code generated for entering and leaving the block will be the same as for a regular block; the fact that it's a try
block will only affect the static data used for stack unwinding.
would it make any difference if the language allowed naked
throw Exception();
statements?
The language does allow that. If there's a suitable handler associated with some try
block on the call stack, then the program jumps to that handler; otherwise, it calls terminate()
since there's nothing to handle the exception.
Do
try
blocks benefit the zero-cost strategy at all?
That makes no sense. They're necessary to identify the set of handlers to consider; from that point of view, they "benefit" all unwinding strategies by allowing them to work in the first place.
Is
try
just a form of comment for modern compilers?
In principle, this could be done without a keyword to identify the block, perhaps associating any catch
block with the preceding statement. So one might regard it as just (rather helpful) documentation.
Upvotes: 1