Proper Destruction of Class Members when an Exception is Thrown inDestructor

A

AnonMail2005

Can someone point me to the specific are of the standard that will
clarify this issue?
I have a class that contains at least one other member. If an
exception is throw in
the destructor, is that member properly destructed?

Sample (non-working) code:

#incude <string>

class Foo
{
public:
// constructor
Foo () {}

// destructor
~Foo ()
{
// do something here that will throw (e.g. some logging)
// is the std::string properly destructed?
}

private:
std::string m_s;
};

thanks
 
L

Leandro Melo

Can someone point me to the specific are of the standard that will
clarify this issue?
I have a class that contains at least one other member.  If an
exception is throw in
the destructor, is that member properly destructed?

Sample (non-working) code:

#incude <string>

class Foo
{
public:
  // constructor
  Foo () {}

  // destructor
  ~Foo ()
    {
      // do something here that will throw (e.g. some logging)
      // is the std::string properly destructed?
    }

private:
  std::string m_s;

};

Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!

If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.

In addition, you'll also be in trouble when using operators like new[]
and delete[].

Bottom line: Don't let your destructors throw.
 
A

AnonMail2005

Can someone point me to the specific are of the standard that will
clarify this issue?
I have a class that contains at least one other member.  If an
exception is throw in
the destructor, is that member properly destructed?
Sample (non-working) code:
#incude <string>
class Foo
{
public:
  // constructor
  Foo () {}
  // destructor
  ~Foo ()
    {
      // do something here that will throw (e.g. some logging)
      // is the std::string properly destructed?
    }
private:
  std::string m_s;

Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!

If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.

In addition, you'll also be in trouble when using operators like new[]
and delete[].

Bottom line: Don't let your destructors throw.

Never use the word never!
 
D

Daniel Pitts

Can someone point me to the specific are of the standard that will
clarify this issue?
Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!

If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.

In addition, you'll also be in trouble when using operators like new[]
and delete[].

Bottom line: Don't let your destructors throw.
Never use the word never!
Except about "Exceptions leaving Destructors"

The reasoning I've heard is: When an exception is thrown from any part
of your code, the stack starts to unwind. This includes calling any
appropriate destructors. If a destructor throws an exception, then what
is supposed to happen? Does the new exception take precedence? Does the
old one trump?

The answer is: I don't care, because it is probably not what I want.
Don't let your destructor throw an exception.

Worse case scenario, let the program die immediately.
 
A

AnonMail2005

On 26 fev, 12:47, "(e-mail address removed)" <[email protected]>
wrote:
Can someone point me to the specific are of the standard that will
clarify this issue?
Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!
If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.
In addition, you'll also be in trouble when using operators like new[]
and delete[].
Bottom line: Don't let your destructors throw.
Never use the word never!

Except about "Exceptions leaving Destructors"

The reasoning I've heard is: When an exception is thrown from any part
of your code, the stack starts to unwind. This includes calling any
appropriate destructors.  If a destructor throws an exception, then what
is supposed to happen? Does the new exception take precedence? Does the
old one trump?

The answer is: I don't care, because it is probably not what I want.
Don't let your destructor throw an exception.

Worse case scenario, let the program die immediately.

It is well defined what happens when an exception is thrown during
stack unwinding, so there is no guessing what will happen.

I found the portion of the standard that actually *answers* my
specific question.
The relevant section is 15.2.2.
 
A

anon

On 26 fev, 12:47, "(e-mail address removed)" <[email protected]>
wrote:
Can someone point me to the specific are of the standard that will
clarify this issue?
Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!
If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.
In addition, you'll also be in trouble when using operators like new[]
and delete[].
Bottom line: Don't let your destructors throw.
Never use the word never!
Except about "Exceptions leaving Destructors"

The reasoning I've heard is: When an exception is thrown from any part
of your code, the stack starts to unwind. This includes calling any
appropriate destructors. If a destructor throws an exception, then what
is supposed to happen? Does the new exception take precedence? Does the
old one trump?

The answer is: I don't care, because it is probably not what I want.
Don't let your destructor throw an exception.

Worse case scenario, let the program die immediately.

It is well defined what happens when an exception is thrown during
stack unwinding, so there is no guessing what will happen.

I found the portion of the standard that actually *answers* my
specific question.
The relevant section is 15.2.2.

I doubt 15.2.2 is relevant, because in 99.99% an exception thrown from a
destructor will terminate the process.

Can not think of an example where 0.01% this is not true.
 
A

AnonMail2005

(e-mail address removed) wrote:
On 26 fev, 12:47, "(e-mail address removed)" <[email protected]>
wrote:
Can someone point me to the specific are of the standard that will
clarify this issue?
Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!
If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.
In addition, you'll also be in trouble when using operators like new[]
and delete[].
Bottom line: Don't let your destructors throw.
Never use the word never!
Except about "Exceptions leaving Destructors"
The reasoning I've heard is: When an exception is thrown from any part
of your code, the stack starts to unwind. This includes calling any
appropriate destructors.  If a destructor throws an exception, then what
is supposed to happen? Does the new exception take precedence? Does the
old one trump?
The answer is: I don't care, because it is probably not what I want.
Don't let your destructor throw an exception.
Worse case scenario, let the program die immediately.
It is well defined what happens when an exception is thrown during
stack unwinding, so there is no guessing what will happen.
I found the portion of the standard that actually *answers* my
specific question.
The relevant section is 15.2.2.

I doubt 15.2.2 is relevant, because in 99.99% an exception thrown from a
destructor will terminate the process.

Can not think of an example where 0.01% this is not true.- Hide quoted text -

- Show quoted text -

Of course it's relevant because it answered my specific question.

*******
15.2.2 says:
An object that is partially constructed or partially destroyed will
have destructors executed for all of its fully constructed subobjects,
that is, for subobjects for which the constructor has completed
execution and the destructor has not yet begun execution. Should a
constructor for an element of an automatic array throw an exception,
only the constructed elements of that array will be destroyed. If the
object or array was allocated in a new-expression, the matching
deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to
free the storage occupied by the object.
******

For an exception thrown from a destructor ***during stack
unwinding***, the *default* action is to terminate the process. So
that only happens during stack unwinding - i.e. when an exception has
already been thrown.
 
A

anon

Of course it's relevant because it answered my specific question.

*******
15.2.2 says:
An object that is partially constructed or partially destroyed will
have destructors executed for all of its fully constructed subobjects,
that is, for subobjects for which the constructor has completed
execution and the destructor has not yet begun execution. Should a
constructor for an element of an automatic array throw an exception,
only the constructed elements of that array will be destroyed. If the
object or array was allocated in a new-expression, the matching
deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to
free the storage occupied by the object.
******

For an exception thrown from a destructor ***during stack
unwinding***, the *default* action is to terminate the process. So
that only happens during stack unwinding - i.e. when an exception has
already been thrown.

Sorry I misunderstood you.

The answer to your question is : yes, all constructed class members will
be properly destructed.

And unless you are doing something like in the following example, your
process should be properly destructed as well :p

struct A
{
~A() { throw "hi"; }
};

int main()
{
try
{
A *a = new A;
try
{
delete(a);
}
catch(...)
{
}
}
catch(...)
{
}
}
 
J

James Kanze

(e-mail address removed) wrote:
On 26 fev, 12:47, "(e-mail address removed)" <[email protected]>
wrote:
Can someone point me to the specific are of the standard that will
clarify this issue?
Well, you should start from a very important C++ guideline which says
that destructors should not throw. Never!
If you implement a destructor that might throw you'll be unable to
rely on others well know C++ idioms. Basically, you won't be able to
write exception-safe code and provide any kind of commit-or-rollback
guarantee.
In addition, you'll also be in trouble when using operators like new[]
and delete[].
Bottom line: Don't let your destructors throw.
Never use the word never!
Except about "Exceptions leaving Destructors"
The reasoning I've heard is: When an exception is thrown
from any part of your code, the stack starts to unwind.
This includes calling any appropriate destructors. If a
destructor throws an exception, then what is supposed to
happen? Does the new exception take precedence? Does the
old one trump?
The answer is: I don't care, because it is probably not
what I want. Don't let your destructor throw an exception.
Worse case scenario, let the program die immediately.
It is well defined what happens when an exception is thrown
during stack unwinding, so there is no guessing what will
happen.
I found the portion of the standard that actually *answers*
my specific question.
The relevant section is 15.2.2.
I doubt 15.2.2 is relevant, because in 99.99% an exception
thrown from a destructor will terminate the process.

That's simply false. Most of the time, an exception thrown from
a destructor will NOT terminate the process.
Can not think of an example where 0.01% this is not true.

class ThrowsInDestructor
{
public:
~ThrowsInDestructor() { throw 42; }
} ;

int
main()
{
try {
ThrowsInDestructor t ;
std::cout << "t constucted" << std::endl ;
} catch ( int i ) {
return i ;
}
return 0 ;
}

The problem isn't that most of the time, throwing from a
destructor will terminate the process. The problem is
guaranteeing that this will never be the case. Something that
is very difficult, if not impossible, for most general purpose
classes (but there exist a very few, special classes, whose sole
purpose is for the destructor to throw).
 

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

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top