Thread: Catching exceptions thrown from constructor of a global instance of a class

  1. #1
    Registered User
    Join Date
    Dec 2012
    Posts
    13

    Question Catching exceptions thrown from constructor of a global instance of a class

    I know that having global variables is not appreciated. But in the book, The C++ programming language, by Bjarne Stroustrup, Author says that " The only way to gain control in case of throw from an initializer of a non local static object is set_unexpected() ". How is it done?How can i gain control?

  2. #2
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    I'm not sure how close to the spec this reference is, but it says that:

    The unexpected handler function... shall end either by teminating (calling terminate or cstdlib's exit or abort) or by throwing an exception (even rethrowing the same exception again).
    So I don't know if you're expecting to "regain control" in the sense of being able to continue execution, but I can't see how you could possibly do that in a sane way. The best I can come up with is this example:

    Code:
    #include <iostream>
    #include <exception>
    #include <cstdlib>
    
    void handler()
    {
        std::cout << "handler()" << std::endl;
        exit(0);
    }
    
    class Object
    {
    public:
        Object() throw() {
            std::set_unexpected(&handler);
            throw std::exception();
        }
    };
    
    Object object;
    
    int main()
    {
    }
    Bottom line: If you want to control what happens when non-local static objects throw exceptions in constructors, use a pointer and initialize it in main().
    Programming and other random guff: cat /dev/thoughts > blogspot.com (previously prognix.blogspot.com)

    ~~~

    "The largest-scale pattern in the history of Unix is this: when and where Unix has adhered most closely to open-source practices, it has prospered. Attempts to proprietarize it have invariably resulted in stagnation and decline."

    Eric Raymond, The Art of Unix Programming

  3. #3
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    You'll need some sort of init mechanism, depending on how much control you need.
    Either a function called from main...constructing the object declared as a pointer.
    Or another global object wrapping this one inside it.

    I'd go with the former,if at all, because of its simplicity.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I'd suggest you need to ask the question of why construction of a static object is throwing an exception at all. Non-local static objects are typically constructed before main() is called (technically they are constructed before any code that uses them is executed, but few compilers are smart enough to wait, so will simply construct them as early as possible during program startup) so it is better to avoid having failures occur, rather than trying to regain control afterward.

    In any event, to answer your question, it is necessary to ensure that set_unexpected() is called before the (potential) failure occurs. This means one of;

    1) calling set_unexpected() in a constructor of some other object. The problem then becomes one of guaranteeing that construction of "other object" does not fail. It also requires that "other object" is constructed first - which is difficult to achieve, since the construction order of non-local static objects is not defined.

    2) calling set_unexpected() in the constructor of a base class. This works, since base class constructors are guaranteed to be called before derived class constructors.

    3) calling set_unexpected() within your constructor that can fail, before it performs whatever action triggers an exception.

    Generally, I would prefer option 2.

    Whichever option you use, the control you get by using set_unexpected() is pretty limited, since the handler function is not allowed to return. The only realistic options are to clean up and terminate the program, or to somehow initiate (by some means specific to your host system) a complete restart of your program.
    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.

  5. #5
    Registered User
    Join Date
    Dec 2012
    Posts
    13
    Thanks for the reply..

    Quote Originally Posted by grumpy View Post
    2) calling set_unexpected() in the constructor of a base class. This works, since base class constructors are guaranteed to be called before derived class constructors.
    Is this how the above step is to be done:
    Code:
    void f()        //Unexpected exception handler
    {
        cout<<"Unexpected handler"<<endl;
    }
    class A            //Base class that performs set_unexpected
    {
        unexpected_handler h;
    public:
        A()
        {
            h=set_unexpected(f);
        }
        ~A()
        {
            set_unexpected(h);
        }
    };
    class B:public A    //Derived class that throws unexpected_exception
    {
    public:
        B() throw ()
        {
            throw 1;
        }
    };
    B b;
    int main()
    {
    }

    It doesn't show the message: "Unexpected handler". I get an exception which is unhandled : System.Runtime.InteropServices.SEHException.
    Last edited by Sajas K K; 12-12-2012 at 06:54 AM. Reason: To improve clarity

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You seem to be using C++/CLI or something, not native C++.
    Also, avoid dynamic exception specificers ( throw() ), as they are deprecated and never worked anyway. If you must use something, use noexcept(false) (requires C++11).
    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.

  7. #7
    Registered User
    Join Date
    Dec 2012
    Posts
    13
    Quote Originally Posted by Elysia View Post
    You seem to be using C++/CLI or something, not native C++.
    Also, avoid dynamic exception specificers ( throw() ), as they are deprecated and never worked anyway. If you must use something, use noexcept(false) (requires C++11).
    Thank you..
    I ran the code in code block. It worked.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The use of a non-local, static object whose constructor can throw, is absolutely insane.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Exceptions in constructor..
    By manasij7479 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2012, 10:01 PM
  2. Global Access to Global Class without so many pointers
    By parad0x13 in forum C++ Programming
    Replies: 1
    Last Post: 11-11-2009, 02:48 PM
  3. Global objects and exceptions
    By drrngrvy in forum C++ Programming
    Replies: 1
    Last Post: 09-29-2006, 07:37 AM
  4. Declaring an instance of a class inside a class
    By nickodonnell in forum C++ Programming
    Replies: 4
    Last Post: 10-01-2005, 11:46 PM
  5. Handling Global Project Wide Exceptions
    By doom in forum C# Programming
    Replies: 0
    Last Post: 09-12-2005, 10:17 AM

Tags for this Thread