Proper Destruction of Class Members when an Exception is Thrown inDestructor

Discussion in 'C++' started by AnonMail2005, Feb 26, 2009.

  1. AnonMail2005

    AnonMail2005 Guest

    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
     
    AnonMail2005, Feb 26, 2009
    #1
    1. Advertisements

  2. AnonMail2005

    Leandro Melo Guest

    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.
     
    Leandro Melo, Feb 26, 2009
    #2
    1. Advertisements

  3. AnonMail2005

    AnonMail2005 Guest

    Never use the word never!
     
    AnonMail2005, Feb 26, 2009
    #3
  4. AnonMail2005

    Daniel Pitts Guest

    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.
     
    Daniel Pitts, Feb 26, 2009
    #4
  5. AnonMail2005

    AnonMail2005 Guest

    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.
     
    AnonMail2005, Feb 26, 2009
    #5
  6. AnonMail2005

    anon Guest

    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.
     
    anon, Feb 27, 2009
    #6
  7. AnonMail2005

    AnonMail2005 Guest

    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.
     
    AnonMail2005, Feb 27, 2009
    #7
  8. AnonMail2005

    anon Guest

    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(...)
    {
    }
    }
     
    anon, Feb 27, 2009
    #8
  9. AnonMail2005

    James Kanze Guest

    That's simply false. Most of the time, an exception thrown from
    a destructor will NOT terminate the process.
    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).
     
    James Kanze, Mar 2, 2009
    #9
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.