Catch a link if an exception variable is not defined

When catching an exception, the standard guide is a throw by value, catch by reference. As far as I understand, this happens for two reasons:

  • If an exception was thrown due to an exception in memory, we will not name the copy constructor, which could potentially terminate the program.
  • If the exception is part of the hereditary hierarchy, we can potentially subject the object to clipping to the exception.

If we have a scenario in which we do not define the name of the exception in the catch block, are these problems (actually 1. since slicing will not be a problem if we do not have a name for the variable) valid?

For example:

catch(my_exception) { ... } 

or

 catch(my_exception &) { ... } 

Is there still the possibility of terminating the program if the exception is caught by value in this case? I feel technically still possible.

Note. I ask about this because I had to revise the code that would put the catch by value in this case. As shown in the question, I'm not entirely sure about the technical impact of any choice, but I think that from the point of view of consistency it is better to catch the link in this case independently (in any case, there is no shortage of searching for the link).

+2
c ++ exception
source share
3 answers

The standard does not require special optimization in the case of an unnamed exception object. On the contrary, then it requires the effect, as if the temporary was initialized by the copy. This copying can lead to dynamic memory allocation.

N3290 ยง15.3 / 16 :
If a name is specified in the exception declaration, it declares a variable that is initialized with a copy (8.5) of the exception object. If the exception declaration indicates the type of the object but does not indicate the name, the temporary (12.2) is initialized with a copy (8.5) from the exception object. The lifetime of a variable or a temporary one ends after the handler exits after the destruction of any automatic objects initialized in the handler.

The paragraph above does not mention catch by reference, and therefore it can be reasonably concluded that it is applied regardless of whether the exception object is caught by reference; that the copy is built anyway.

However, this contradicts the following paragraph:

N3290 ยง15.3 / 17 :
When a handler declares a mutable object, any changes to this object will not affect the temporary object that was initialized by running the throw statement. When the handler declares a reference to a mutable object, any changes to the referenced object are changes to the initialized temporary object when the throw expression was executed and will have the effect that the object is discarded.

So, the declared type T& (with T not const ) is the only case when C ++ 11 requires a direct reference to an abandoned object instead of copying. And this is also in C ++ 03, except that C ++ 03 contains additional wording about as-if optimization. So, for formal preference should be for

  catch( T& name ) 

and

  catch( T& ) 

However, I have always encountered exceptions such as catch( T const& ) . From a practical point of view, it can be assumed that the compiler optimizes this for direct reference to an abandoned object, even if it is possible to develop cases where the observed program effect will then be non-standard. For example <evil grin>

 #include <stdio.h> #include <stdexcept> struct Error : std::runtime_error { public: static Error* pThrown; char const* pMessage_; Error() : std::runtime_error( "Base class message" ) , pMessage_( "Original message." ) { printf( "Default-construction of Error object.\n" ); pThrown = this; } Error( Error const& other ) : std::runtime_error( other ) , pMessage_( other.pMessage_ ) { printf( "Copy-construction of Error obejct.\n" ); } char const* what() const throw() { return pMessage_; } }; Error* Error::pThrown = 0; int main() { printf( "Testing non-const ref:\n" ); try { throw Error(); } catch( Error& x ) { Error::pThrown->pMessage_ = "Modified message."; printf( "%s\n", x.what() ); } printf( "\n" ); printf( "Testing const ref:\n" ); try { throw Error(); } catch( Error const& x ) { Error::pThrown->pMessage_ = "Modified message"; printf( "%s\n", x.what() ); } } 

With MinGW g ++ 4.4.1 and Visual C ++ 10.0, the output is & hellip;

 Testing non-const ref:
 Default-construction of Error object.
 Modified message.

 Testing const ref:
 Default-construction of Error object.
 Modified message

A pedantic formalist may say that both compilers are inappropriate, without creating a copy for the Error const& case. A practical practitioner can say hey, what else did you expect? And I say that the wording in the standard here is very far from perfect, and that, if anything, it should be expected that the clarification will explicitly allow the conclusion above, so that catching the const reference is safe and most effective.

Summarizing by. question OP:

  • Link Capture won & rsquo; t calls the copy constructor, which can potentially terminate program execution.

  • The standard only guarantees this for reference to non const .

  • In practice, as shown, it is also guaranteed to reference const , even when program results are then exposed.

Cheers and hth.,

+5
source share

I would rather catch the link. The compiler may throw an exception as an optimization and not make copies, but this is only an option. The trick of the link gives you certainty.

+1
source share

There may be invisible data associated with your exception, for example. a vtable .

A vtable is an invisible data structure that contains information about where to find specific, polymorphic (i.e. virtual ) member functions. This table generally costs a bit of memory, which is stored in the object itself. This may be the size of a pointer to some external table or even a complete table. As always, it depends.

+1
source share

All Articles