Thread: Problem throwing exception from destructor (GCC 3.4.5)

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Question Problem throwing exception from destructor (GCC 3.4.5)

    I have a class that throws an exception from the destructor "by design". The exception is caught properly, but after the catch block is executed, GCC invokes std::terminate. Here's an example:

    Code:
    #include <iostream>
    #include <stdexcept>
    
    struct fatal
    {
        ~fatal( void )
        {
            if( !std::uncaught_exception( ) )
                throw *this;
        }
    };
    
    int main( void )
    {
        try
        {
            fatal( );
        }
        catch( fatal const& )
        {
            std::cout << "Exception caught!" << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    Output:

    Exception caught!

    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
    Now, as I understand it, std::terminate should only be called if an exception is thrown from a destructor while the stack is being unwound (another exception is already being processed). Am I mistaken, or is this a bug with GCC?
    Last edited by Sebastiani; 06-13-2010 at 12:45 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Never use `std::uncaught_exception' in any production code. Ever. It is guaranteed to fail eventually, and a few compilers are designed for `std::uncaught_exception' to return false in any case.

    Am I mistaken, or is this a bug with GCC?
    *shrug*

    It doesn't matter, but a guess says that the environmental copy of the `fatal' instance you catch is being destroyed correctly after the `catch' block which then throws another exception.

    [Edit]
    Try this slight change to see what I'm saying.
    [/Edit]

    Soma

    Code:
    #include <iostream>
    #include <stdexcept>
    
    struct fatal
    {
    	 fatal()
        {
    		  std::cout << "fatal()" << '\n';
        }
        fatal(const fatal &)
        {
    		  std::cout << "fatal(const fatal &)" << '\n';
        }
        fatal & operator = (const fatal &)
        {
    		  std::cout << "fatal & operator = (const fatal &)" << '\n';
            return *this;
        }
        ~fatal( void )
        {
    		  std::cout << "~fatal( void )" << '\n';
            if( !std::uncaught_exception( ) )
                throw *this;
        }
    };
    
    int main( void )
    {
        try
        {
            fatal( );
        }
        catch( fatal const& )
        {
            std::cout << "Exception caught!" << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    Last edited by phantomotap; 06-13-2010 at 01:04 AM. Reason: none of your business

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by phantomotap View Post
    O_o
    It doesn't matter, but a guess says that the environmental copy of the `fatal' instance you catch is being destroyed correctly after the `catch' block which then throws another exception.
    Doh! I can't believe I missed that. Thanks, Soma!
    Last edited by Sebastiani; 06-13-2010 at 01:10 AM. Reason: nor yours
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Yep.

    Reason: nor yours
    NO! Now I'm all curious...

    Soma ;_;

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Out of curiosity, what is your requirement that calls for an exception to be thrown by a destructor, by design?
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by grumpy View Post
    Out of curiosity, what is your requirement that calls for an exception to be thrown by a destructor, by design?
    The class basically stores error codes/messages. If the object isn't "checked" before it's destroyed, it acts as an exception, eg:

    Code:
    error e = some_tricky_operation( );
    if( e ) /* do something */;
    some_tricky_operation( ); // if an error is returned here, an exception is thrown
    Last edited by Sebastiani; 06-13-2010 at 09:12 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Is this honestly a good idea? Do you intend to catch the exception somewhere later?
    If not, wouldn't an assertion be a better idea?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Elysia View Post
    Is this honestly a good idea? Do you intend to catch the exception somewhere later?
    If not, wouldn't an assertion be a better idea?
    (1) Depends on who you ask.
    (2) Again, yes, if an error is set and the returned object isn't tested, it gets propagated as an exception and (presumably) handled at a higher level.
    (3) See #2.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, but seriously, the C++ standard mandates that if an exception is thrown during stack unwinding, it will call terminate. But you cannot make sure it's currently unwinding (unless you would set some global state or some such).
    So you could throw an exception from the destructor so long as you make sure no two of these objects are destroyed before stack unwinding is done.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Elysia View Post
    No, but seriously, the C++ standard mandates that if an exception is thrown during stack unwinding, it will call terminate. But you cannot make sure it's currently unwinding (unless you would set some global state or some such).
    So you could throw an exception from the destructor so long as you make sure no two of these objects are destroyed before stack unwinding is done.
    Right, and that was the reason for checking std::uncaught_exception( ). Unfortunately, GCC blithely returns false, in any case, so no guarantees there, I suppose. That said, I can only think of one situation where another exception could crop up in the process - std::bad_alloc, in which case the app is doomed anyway, so the risk is really minimal, methinks (could be wrong, tho).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I thought throwing an exception from a destructor was a bad thing. In fact I remember reading in a book somewhere that says you should never do it. It might have even been Bjarne's book.

    If by design you must throw from a destructor then I would call that a flawed design.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    It may have been just about any of the books by Herb Sutter, Scott Meyer, Andrew Koenig, or Bjarne Stroustrup. They've all referenced the danger at one point or the other.

    Soma

  13. #13
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Bubba View Post
    I thought throwing an exception from a destructor was a bad thing. In fact I remember reading in a book somewhere that says you should never do it. It might have even been Bjarne's book.

    If by design you must throw from a destructor then I would call that a flawed design.
    Yep, and I've finally come around to the same conclusion. It was a fun experiment, anyway.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bin packing problem....
    By 81N4RY_DR460N in forum C++ Programming
    Replies: 0
    Last Post: 08-01-2005, 05:20 AM
  2. Replies: 5
    Last Post: 12-03-2003, 05:47 PM
  3. Another Exception problem
    By Hankyaku in forum C++ Programming
    Replies: 1
    Last Post: 04-08-2003, 12:46 PM
  4. Exception specifications: good or bad?
    By Just in forum C++ Programming
    Replies: 0
    Last Post: 02-19-2003, 09:19 PM
  5. problem with output
    By Garfield in forum C Programming
    Replies: 2
    Last Post: 11-18-2001, 08:34 PM