I understand there should be no exception thrown from destructor. But
exception will block the remaining code to be executed until catch block.
In my destructor, I free resources step by step. But at some first step,
there may be exception in destructor, so I suspect the remaining resources
can not be freed correctly. In my class, I use member variable to hold
resources.
My questions are,
- My current solution is to declare each member as smart pointer, so that to
ensure the destructor will be called.
- I am not sure whether my concern is correct or no such issue -- e.g.
member's destructor will always be called or not, even if I do not wrap them
with auto_ptr?
thanks in advance,
George
Uh... Why the "but"? There should be no exception thrown from
destructor because if the destructor is called during stack unwinding
due to some other exception, the program will terminate. And if the
exception is thrown, the execution of the destructor will be
interrupted. At least that's how I understand it.
> In my destructor, I free resources step by step. But at some first step,
> there may be exception in destructor,
You do understand that throwing from a destructor is a VERY BAD
IDEA(tm), right?
> so I suspect the remaining resources
> can not be freed correctly. In my class, I use member variable to hold
> resources.
>
> My questions are,
>
> - My current solution is to declare each member as smart pointer, so that to
> ensure the destructor will be called.
The normal execution of the code will be interrupted if the exception is
thrown. That means that neither the destructors for any data members
nor for any base classes will be executed. Whatever their types are.
> - I am not sure whether my concern is correct or no such issue -- e.g.
> member's destructor will always be called or not, even if I do not wrap them
> with auto_ptr?
No, it's actually worse. No destructor will be called regardless of
whether you'll wrap them.
I am not entirely sure of this, let's hope somebody corrects me...
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
George schrieb:
> I understand there should be no exception thrown from destructor. But
> exception will block the remaining code to be executed until catch block.
>
> In my destructor, I free resources step by step. But at some first step,
> there may be exception in destructor,
Why do you throw an exception in a destructor? You should not not not not do that!
Norbert
I do not throw exception. I call some member's destructor, and the
destructor of the member throw exception, I just catch it at the end of my
class destructor -- but it changes the flow of the code so that other code in
destructor is not called.
One more question, if the class member has destructor, even if
- we do not call it exeplicitly in the whole class's destructor;
- or because of exception execution flow, it is not executed
its destructor will be called when the current object instance destructs?
regards,
George
I am sorry that I have made myself understood enough. I write some code to
show my issues.
Generally, my question is if the class member has destructor, even if
- we do not call it exeplicitly in the whole class's destructor;
- or because of exception execution flow, it is not executed
its destructor will be called when the current object instance destructs?
class Goo;
class Zoo;
class Foo
{
Goo* pG;
Zoo* pZ;
// destructor
virtual ~Foo()
{
try
{
// free some resources, but the operation may throw exception
// if exception is thrown in function FreeResources, delete pG and delete
pZ
// will not be executed, are there any leak?
FreeResources();
delete pG;
delete pZ;
}
catch (...)
{
}
}
}
regards,
George
I'm not sure what you mean exactly by above question. Here are some
facts about C++ that you should keep in mind:
- Although the C++ language doesn't forbids it, you should never throw
exceptions from your destructors. If you use libraries whose objects
throw exceptions in their destructors, consider the library broken and
ask for a fix.
- The destructors of every member is automatically invoked when the
destructor of the
object has finished (of course, unless the destructor throws an
exception. In this case the members won't get destructed). Note that
there is a big difference between smart pointer members and ordinary
pointer members: The smart pointer member will delete the contained
pointer and thus invoke the destructor of the member object. The
destructor of ordinary pointers will do nothing (this is the main
source of memory leaks).
>
> class Goo;
>
> class Zoo;
>
> class Foo
> {
> Goo* pG;
> Zoo* pZ;
>
> // destructor
> virtual ~Foo()
> {
> try
> {
> // free some resources, but the operation may throw exception
> // if exception is thrown in function FreeResources, delete pG and delete
> pZ
> // will not be executed, are there any leak?
> FreeResources();
> delete pG;
> delete pZ;
If FreeSources throws an exception, the members pG and pZ won't be
deleted and pG's and pZ's destructor won't get called. Better use
smart pointers.
> }
> catch (...)
> {
>
> }
> }
>
> }
>
> regards,
> George
I have fixed my code. I write two destructors below. Could you help to
review both of them are good code -- no resource leak, even if there is
exception in function FreeResources please?
class Goo;
class Zoo;
class Foo
{
auto_ptr<Goo> pG;
auto_ptr<Zoo> pZ;
// destructor
virtual ~Foo()
{
try
{
// free some resources, but the operation may throw exception
// if exception is thrown in function FreeResources, delete pG and delete
pZ
// will not be executed, are there any leak?
FreeResources();
delete pG;
delete pZ;
}
catch (...)
{
}
}
// destructor
virtual ~Foo()
{
try
{
// free some resources, but the operation may throw exception
// if exception is thrown in function FreeResources, delete pG and delete
pZ
// will not be executed, are there any leak?
FreeResources();
}
catch (...)
{
}
}
}
regards,
George
No, it is not good code. auto_ptr will destroy the reference object
automatically, you should not call delete on an auto_ptr.
> No, it is not good code. auto_ptr will destroy the reference object
> automatically, you should not call delete on an auto_ptr.
I understand we can not call delete on auto_ptr. " destroy the reference
object" -- I think you mean destroy object instance wrapped by pG and pZ?
If yes, in my code, what is wrong to release pG and pZ in destructor? It is
normal senses to release composed object (member variable) in destructor.
regards,
George
I meant "referenced", sorry about the missing letter. Yes, that's the
object the smart pointer points to.
>
> If yes, in my code, what is wrong to release pG and pZ in destructor?
> It is normal senses to release composed object (member variable) in
> destructor.
auto_ptr has ownership of the object it is pointing to. Therefore you
should not delete the object unless you first take ownership away from
auto_ptr because you will confuse auto_ptr and maybe crash your program.
>
>
> regards,
> George
I have corrected my code, could you review again whether the code is correct
and no leak please? :-)
[Code]
class Goo;
class Zoo;
class Foo
{
auto_ptr<Goo> pG;
auto_ptr<Zoo> pZ;
// destructor
virtual ~Foo()
{
try
{
// free some resources, but the operation may throw exception
// if exception is thrown in function FreeResources, delete pG and delete pZ
// will not be executed, are there any leak?
FreeResources();
}
catch (...)
{
}
}
}
[/Code]
regards,
George
The code will not leak, but you should ask why FreeResources throws an
exception if you are just going to ignore it. Try to redesign FreeResources
so that it cannot fail.
In my application, I will free database handle for every object instance
which holds one, so I put it into destructor.
But destructor can not throw exception, so I catch it and ignore it. The
reason why there is exception when I free database handle using ADO.Net is, I
tested in some rare conditions if database connection is forced to be closed
before I call database handle close function, there will be exception thrown,
so I want to handle this situation.
Any comments or advice?
regards,
George