The object that is thrown

P

Pat

Hi,

Where does the object that is "thrown" by the throw statement live? For
example, if I write this code:


if (something_went_wrong)
{
my_exception_class x;

x.set_text("Something went wrong");
x.set_error_number(123);
x.set_something_else(true);

throw x;
}


I would expect (based on very limited experience with try/catch/throw) that
"x" would be created on the stack. But the documentation for
try/catch/throw says that the stack is "unwound" when the throw statement
is executed, and that objects on the stact are destructed. So "x" would
cease to exist, wouldn't it? And the catch block would not "catch"
anything at all? Or does the thing that is "thrown" get special treatment
by the compiler?

Thanks!
 
R

Ron

I would expect (based on very limited experience with try/catch/throw) that
"x" would be created on the stack.  But the documentation for
try/catch/throw says that the stack is "unwound" when the throw statement
is executed, and that objects on the stact are destructed.  So "x" would
cease to exist, wouldn't it?  And the catch block would not "catch"
anything at all?  Or does the thing that is "thrown" get special treatment
by the compiler?

Throw copies the thrown object to an undisclosed location prior to the
unwinding starting. It is safe to throw local variables that will
get unwound or temporaries.
 
R

red floyd

Throw copies the thrown object to an undisclosed location prior to the
unwinding starting.

It then stays at the undisclosed location until Dick Cheney kicks it
out. :)
 
J

James Kanze

Where does the object that is "thrown" by the throw statement
live? For example, if I write this code:
if (something_went_wrong)
{
my_exception_class x;
x.set_text("Something went wrong");
x.set_error_number(123);
x.set_something_else(true);
throw x;
}
I would expect (based on very limited experience with
try/catch/throw) that "x" would be created on the stack.

"x" is (unless some optimizations occur).
But the documentation for try/catch/throw says that the stack
is "unwound" when the throw statement is executed, and that
objects on the stact are destructed. So "x" would cease to
exist, wouldn't it?
Yes.

And the catch block would not "catch" anything at all?

It catches a copy that was made before x was destructed.
Or does the thing that is "thrown" get special treatment by
the compiler?

The formal semantic of a throw is that the thrown object (which
can be a local variable or a temporary) will be copied
"somewhere" where it won't be destructed until it should be.
From the standard:

A throw-expression initializes a temporary object,
called the exception object[...] The temporary is an
lvalue and is used to initialize the variable named in
the matching handler.[...]

The memory for the temporary copy of the exception being
thrown is allocated in an unspecified way, except as
noted in 3.7.4.1. The temporary persists as long as
there is a handler being executed for that exception. In
particular, if a handler exits by executing a throw;
statement, that passes control to another handler for
the same exception, so the temporary remains. When the
last remaining active handler for the exception exits by
any means other than throw; the temporary object is
destroyed and the implementation may deallocate the
memory for the temporary object; any such deallocation
is done in an unspecified way. The destruction occurs
immediately after the destruction of the object declared
in the exception-declaration in the handler.

I'm not too happy with the first sentence above. In most other
contexts of the standard, "temporary object" has a very definite
meaning, different from what is meant here. The important
things to note, however is that 1) it is a copy that is thrown
(although the compiler can optimize the copy out in certain
specific cases), and 2) the object actually thrown has a
specific lifetime, unrelated to any of the other lifetimes the
standard defines (and I guess 3) the rest is the compiler's
problem, not yours).

You might want to try something like:

#include <iostream>
#define TRACE( what ) std::cout << #what ", this = " << this <<
std::endl

class X
{
public:
X() { TRACE( ctor ) ; }
X( X const& ) { TRACE( copy ) ; }
X& operator=( X const& ) { TRACE( asgn ) ; return *this ; }
~X() { TRACE( dtor ) ; }
} ;

void
f()
{
std::cout << "in f()" << std::endl ;
X localX ;
std::cout << "before throw" << std::endl ;
throw localX ;
}

int
main()
{
try {
f() ;
} catch ( X const& x ) {
std::cout << "in catch, &x = " << &x << std::endl ;
}
return 0 ;
}

to see exactly what your implementation does.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,879
Members
47,416
Latest member
LionelQ387

Latest Threads

Top