Topic: a question about temporary exception object


Author: nimel@hem1.passagen.se
Date: 1998/11/07
Raw View
In article <3642A62C.CF2FC315@ccnet.com>,
  Gilbert Chang <gchang@ccnet.com> wrote:
>
> According to the standard, the constructor and the destructor of Foo
> should be called exactly once for each in the first case, but they could
> be called either once for each or twice for each.  Is my understanding
> correct?
>
> I experimented with VC++6.0.  In both cases, the constructor was called
> once, but the destructor was called twice.  Did I do something wrong or
> is the compiler simply broken?

I tried the same thing on VC++ 6.0. For me both the constructor and
the destructor was called once when catching by reference, and
twice when catching by value. My guess is that you forgot to count
the copy constructor. Below is the output from my test:

begin
throwing Foo
Foo ctor
caught Foo&
Foo dtor
throwing Foo
Foo ctor
Foo copy ctor
caught Foo
Foo dtor
Foo dtor
end

/Niklas Mellin

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Gilbert Chang <gchang@ccnet.com>
Date: 1998/11/06
Raw View
<quote from the C++ standard draft>
 The  memory  for  the  temporary copy of the exception being thrown is
  allocated   in   an   unspecified   way,   except    as    noted    in
  _basic.stc.dynamic.allocation_.   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 con-
  trol to another handler for  the  same  exception,  so  the  temporary
  remains.  If the use of the temporary object can be eliminated without
  changing the meaning of the program except for the execution  of  con-
  structors  and  destructors  associated  with the use of the temporary
  object (_class.temporary_), then the exception in the handler  can  be
  initialized  directly with the argument of the throw expression.  When
  the thrown object is a class object, and the copy constructor used  to
  initialize  the  temporary copy is not accessible, the program is ill-
  formed (even when the temporary object could otherwise be eliminated).
  Similarly,  if  the  destructor for that object is not accessible, the
  program is ill-formed (even when the temporary object could  otherwise
  be eliminated).
<end of quote>

Consider the following code snippets:

//
// class Foo
// {
// public:
//     Foo();
//    ~Foo();
// };
//

try
{
    throw Foo();
}
catch(Foo & foo)
{
}

VS.

try
{
    throw Foo();
}
catch(Foo foo)
{
}

According to the standard, the constructor and the destructor of Foo
should be called exactly once for each in the first case, but they could
be called either once for each or twice for each.  Is my understanding
correct?

I experimented with VC++6.0.  In both cases, the constructor was called
once, but the destructor was called twice.  Did I do something wrong or
is the compiler simply broken?

Thanks

Gilbert Chang



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/11/06
Raw View
In article <3642A62C.CF2FC315@ccnet.com>, Gilbert Chang
<gchang@ccnet.com> writes
>I experimented with VC++6.0.  In both cases, the constructor was called
>once, but the destructor was called twice.  Did I do something wrong or
>is the compiler simply broken?

Did you instrument the copy ctor? (because forgetting that is the
commonest cause for an apparent mismatch between documented ctors and
dtors)

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Ron Natalie <ron@sensor.com>
Date: 1998/11/07
Raw View
>
> I experimented with VC++6.0.  In both cases, the constructor was called
> once, but the destructor was called twice.  Did I do something wrong or
> is the compiler simply broken?
>

I'm only running VC++ 5, but is it perhaps that you forgot
to put a print in your copy constructor?  I compiled your
test with my own Foo class with prints in the constructors
and destructors and got this:


Foo()
CAUGHT
~Foo()
Foo()
Foo(Foo&)
CAUGHT
~Foo()
~Foo()
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: AllanW@my-dejanews.com
Date: 1998/11/07
Raw View
In article <3642A62C.CF2FC315@ccnet.com>,
  Gilbert Chang <gchang@ccnet.com> wrote:

> // class Foo
> // {
> // public:
> //     Foo();

ADD:     Foo(const Foo&);

> //    ~Foo();
> // };
> //
>
> try
> {
>     throw Foo();
> }
> catch(Foo & foo)
> {
> }
>
> VS.
>
> try
> {
>     throw Foo();
> }
> catch(Foo foo)
> {
> }
>
> I experimented with VC++6.0.  In both cases, the constructor was called
> once, but the destructor was called twice.  Did I do something wrong or
> is the compiler simply broken?

Give Foo a copy constructor, as shown above. The default
constructor was called once, the copy constructor was called
once, and both copies were eventually destructed. This is
correct behavior.

As a rule of thumb, always assume you've made a mistake before
you blame the compiler. There are exceptions to that rule, of
course, but the assumption is the safe way to go.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/11/07
Raw View
Gilbert Chang wrote:
 >
 > Consider the following code snippets:
 >
 > //
 > // class Foo
 > // {
 > // public:
 > //     Foo();
 > //    ~Foo();
 > // };
 > //
 >
 > try
 > {
 >     throw Foo();
 > }
 > catch(Foo & foo)
 > {
 > }
 >
 > VS.
 >
 > try
 > {
 >     throw Foo();
 > }
 > catch(Foo foo)
 > {
 > }
 >
 > According to the standard, the constructor and the destructor of Foo
 > should be called exactly once for each in the first case, but they
 > could be called either once for each or twice for each.  Is my
 > understanding correct?

In the most literal sense, with no optimizations, the Foo() should cause
a temporary object to be constructed on the stack. Then the throw should
copy the Foo into some safe memory that is unaffected by the stack
unwinding. Then, in the second case, the catch should copy the object a
third time. However, the standard always allow copies of temporaries to
be optimized away, even if their constructors and destructors are
nontrivial, as long as no other semantic changes result. And in
practice, compilers are smart enough to know that the Foo can originally
be constructed into the safe memory where it will live while the stack
is unwound. In fact, the compiler may even construct the foo directly
into the stack space allocated for foo in the second catch clause.
However, I don't think this is typical.

--

Ciao,
Paul
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]