 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
wij@seed.net.tw Guest
|
Posted: Sun Mar 20, 2005 1:59 am Post subject: Derived constructor throwed, base did not destroy |
|
|
Hi All:
I searched the google for this question, the answers found says
all constructed objects will be destroyed. But the following codes
does not seem to agree. It is the same if ~D throws.
The compiler is g++. Thank you.
class B {
public:
B() { std::cout << "B"; }
~B() { std::cout << "~B"; }
};
class D : public B {
public:
D() : B()
{
std::cout << "D";
// Test showed ~B is not called. Program displays "BD"
throw int(1); // ~B() is not called
}
~D() {
std::cout << "~D";
// Test showed ~B is not called
// throw int(0); // ~B() is not called
}
};
int main(void)
{
D d;
return(0);
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Sun Mar 20, 2005 9:10 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
<wij (AT) seed (DOT) net.tw> wrote
| Quote: | I searched the google for this question, the answers found says
all constructed objects will be destroyed. But the following codes
does not seem to agree.
|
This is because your sample code triggers a special case: the
exception being thrown is not caught, so terminate() will be
called and the program will exit immediately.
In this situation, it is unspecified whether stack unwinding
occurs before the call to terminate or not.
If you modify the code as follows to avoid program termination,
things will happen as expected:
int main(void)
{
try{
D d;
}
catch(...) { }
return(0);
};
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
pranjal_srivastava@hotmai Guest
|
Posted: Mon Mar 21, 2005 4:16 pm Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
Hi,
If a exception is thrown while constructing an object...its Dtor is
never called.
You have to specifically handle all the exceptions in the Ctor.
Same is the case here....The ctor of D throws exception so dtor will
never be called.
-Pranjal
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Tue Mar 22, 2005 1:52 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
[email]pranjal_srivastava (AT) hotmail (DOT) com[/email] wrote:
| Quote: | Hi,
If a exception is thrown while constructing an object...its Dtor is
never called.
You have to specifically handle all the exceptions in the Ctor.
Same is the case here....The ctor of D throws exception so dtor will
never be called.
|
If the ctor of D throws, then the *dtor of D* will never be called, as
you say. But we are talking about the *dtor of B*, here. The dtor or B
*will* be called, because B is a fully constructed sub-object once the
flow enters the body of D: (§15.2/2).
I agree with Ivan Vecerina that the problem must be caused by the lack
of a try-block, a fact that allows the program to call terminate()
without unwinding the stack (§15.5.1/2).
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Vinzenz Feenstra Guest
|
Posted: Fri Mar 25, 2005 11:53 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
Hi,
the real reason is, that you don't see the complete output, because
std::cout is buffered.
Try the same test with std::cerr instead of std::cout and you'll see
that the D'tors will be called.
BR
Vinzenz
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wij@seed.net.tw Guest
|
Posted: Sat Mar 26, 2005 4:52 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
| Quote: | ...the
exception being thrown is not caught, so terminate() will be
called and the program will exit immediately.
In this situation, it is unspecified whether stack unwinding
occurs before the call to terminate or not.
|
Thanks for the answer. I made an experiment to confirm a
consequence(see below). Hope this will be fixed, dont know which
part is responsible, though.
class T {
public:
T() { std::cerr << "T"; }
~T() { std::cerr << "~T"; }
};
void g(void)
{
D d;
}
void f(void)
{
T t;
g();
}
int main(void)
{
f();
};
The program output "TBD"(terminated), instead of expected
TBD~B~T
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wij@seed.net.tw Guest
|
Posted: Sat Mar 26, 2005 9:30 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
| Quote: | Try the same test with std::cerr instead of std::cout and you'll see
that the D'tors will be called.
|
Using std::cerr results the same on my machine. This may be valid
though.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Sat Mar 26, 2005 9:47 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
"Vinzenz Feenstra" <evilissimo (AT) web (DOT) de> wrote
| Quote: | the real reason is, that you don't see the complete output, because
std::cout is buffered.
Not correct. The fact is that, if the program is terminated because |
the exception was not caught, it is implementation-defined whether
any destructors of stack-based objects will be called or not.
Here's the Chapter and verse in the C++ standard:
15.3/9 If no matching handler is found in a program, the function
terminate() is called; whether or not the stack is unwound before this call
to terminate() is implementation defined
| Quote: | Try the same test with std::cerr instead of std::cout and you'll see
that the D'tors will be called.
Of course, buffering of std::cout also could be causing the symptom, |
but eventually the previous output would be truncated as well.
Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Sat Mar 26, 2005 5:38 pm Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
<wij (AT) seed (DOT) net.tw> wrote
| Quote: | ...the
exception being thrown is not caught, so terminate() will be
called and the program will exit immediately.
In this situation, it is unspecified whether stack unwinding
occurs before the call to terminate or not.
Thanks for the answer. I made an experiment to confirm a
consequence(see below). Hope this will be fixed, dont know which
part is responsible, though.
|
I'm not sure what you meant by "this will be fixed". The behavior
you are observing is conform to the standard, and is reasonable
IMO. terminate() is an extreme solution used by the runtime
when it sees nothing left to do to recover from an error.
Not catching an exception that may be thrown is the real
bug in the program.
If you want to ensure that the destructors are called, just
add a try-catch block in your main program, as suggested
in my previous post.
Again:
int main()
{
try {
f();
}
catch(...) { return EXIT_FAILURE; }
return EXIT_SUCCESS;
}
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Sun Mar 27, 2005 2:19 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
[email]wij (AT) seed (DOT) net.tw[/email] wrote:
| Quote: |
int main(void)
{
f();
};
The program output "TBD"(terminated), instead of expected
TBD~B~T
|
What's that going to prove? I repeat, it's the lack of the try-block
that causes the problem. In fact if you replace function main with
int main()
{
try
{
f();
}
catch(...)
{}
}
you get the result you expect (tried on VC++7.1, but you should get the
same output on any conformant compiler).
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wij@seed.net.tw Guest
|
Posted: Mon Mar 28, 2005 1:33 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
| Quote: | I'm not sure what you meant by "this will be fixed". The behavior
you are observing is conform to the standard, and is reasonable
IMO. terminate() is an extreme solution used by the runtime
when it sees nothing left to do to recover from an error.
|
So, I don't have to implement every class like this:
class T {
T() try {
...
any_function();
}
catch(...) {
// *** Disclaimer ***
// Throwing in the above try block is conditionally caught.
// The following is executed depending not on this class.
// User of this class should have a catch handler (need not
// to be relavent to this internal handler)
...
};
};
| Quote: | IMO. terminate() is an extreme solution used by the runtime
|
terminate() is OK for me (I don't consider it extreme by itself)
What does IMO represent? I am new on the internet world, there's lots
of these!
{"IMO" == "In my opinion". You might want to have a look at the Jargon File for
information on acronyms: <http://www.catb.org/~esr/jargon/>, although it
only lists the form "IMHO"... -mod/dk}
| Quote: | Not catching an exception that may be thrown is the real
bug in the program.
|
Agree. But I did as in the example above.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wij@seed.net.tw Guest
|
Posted: Mon Mar 28, 2005 1:43 am Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
| Quote: | What's that going to prove? I repeat, it's the lack of the try-block
...
|
I can't prove anything but to figure out an consequence from
the given answer to work around my encounter. I got it, the consequence
is byproduct. Please see also the others in this thread.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Vecerina Guest
|
Posted: Mon Mar 28, 2005 12:04 pm Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
<wij (AT) seed (DOT) net.tw> wrote
| Quote: | I'm not sure what you meant by "this will be fixed". The behavior
you are observing is conform to the standard, and is reasonable
IMO. terminate() is an extreme solution used by the runtime
when it sees nothing left to do to recover from an error.
So, I don't have to implement every class like this:
class T {
T() try {
...
any_function();
}
catch(...) {
// *** Disclaimer ***
// Throwing in the above try block is conditionally caught.
// The following is executed depending not on this class.
// User of this class should have a catch handler (need not
// to be relavent to this internal handler)
...
};
};
|
What is the above intended to achieve?
All you need is 1 exception handler, for example in the main()
function (as in the example I wrote). The destructors of
all stack-allocated objects will then be called if an
exception is thrown.
And this is all standard practice and standard behavior - nothing
worth a specific comment or disclaimer in the implementation
of a class.
| Quote: | IMO. terminate() is an extreme solution used by the runtime
terminate() is OK for me (I don't consider it extreme by itself)
|
terminate() is ok if you do not need any destructors to be called.
Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wij@seed.net.tw Guest
|
Posted: Mon Mar 28, 2005 11:48 pm Post subject: Re: Derived constructor throwed, base did not destroy |
|
|
The code sample was a big mistake (out of overlook in mixed evaluation)
I apologize the disturbance.
| Quote: | What is the above intended to achieve?
|
A bad respond to "> I'm not sure what you meant by "this will be
fixed""
It should be the 'using logic when destructors will be called' which
troubled
me. (It probably not good out of here without leaving things clear, if
this
have not been disscussed. I skipped this topic in learning C++.)
Quote 15.3/9: If no matching handler is found in a program, the
function
terminate() is called; whether or not the stack is unwound before this
call
to terminate() is implementation defined.
What about:
1. Rephrasing for use of 15.3/9
If no matching handler is found, destructors in the call chain may or
may not
be called(stack unwinding), program behavior relying on stack unwinding
is in
this case implementation-defined, thus not standard conforming.
2. Consequence
To be standard conforming, a program should provide handler
'catch(...)' in
main(..) to catch all possible object thrown. (not just catch
specifics)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|