Thread: Dealing With Exception From Initialization

  1. #1
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465

    Dealing With Exception From Initialization

    Okay. That title was wierd to phrase. Really it's more like this. I have an object that is a field of my class that I construct using an initializer list, and it's constructor has the potential of throwing an exception. I don't have any idea how I would deal with handling that exception.

    It's really akin to something like:

    Code:
    struct s
    {
            s() : p(new int()) { }
            ~s() { delete p; }
    
            int * p;
    }
    How would you deal with new throwing an exception?

  2. #2
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    There is no need to deal with it inside that class (in fact it's impossible to do it). You'd need to catch that exception wherever you make an object of that class.

    Oh, and the big three rule applies here: If you make any one of: copy constructor, assignment operator, or destructor, you generally need all three.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  3. #3
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Do you mean you're worried that 'new' will throw a bad_alloc exception? If that's the only possible exception to be thrown from the constructor, then there isn't much to do.

    On the other hand, if your constructor throws another exception then you'll potentially have a memory leak (since the destructor won't be called).
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  4. #4
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    I was actually just making a wierd solution around the fact that I can't install the dxsdk for real. Here's this little nested class I made to handle raii of a loaded library. It has a totally wierd ass design, it's just making up wierd solutions as I go along.

    Code:
        struct f
        {
            HMODULE l;
    
            f( LPCTSTR lib, LPCSTR foo, LPCSTR bar ) throw(...)
            {
                if( l = ::LoadLibrary( lib ) )
                {
                    XD3DXMatrixTranslation      = reinterpret_cast<D3DMATRIX * ( WINAPI * )( D3DMATRIX *, float, float, float)>         ( ::GetProcAddress( l, foo ) );
                    XD3DXMatrixPerspectiveFovLH = reinterpret_cast<D3DMATRIX * ( WINAPI * )( D3DMATRIX *, float, float, float, float )>( ::GetProcAddress( l, bar ) );
    
                    if( !XD3DXMatrixTranslation || !XD3DXMatrixPerspectiveFovLH )
                    {
                        throw std::exception();
                    }
                }
                else 
                    throw std::exception();
            }
            ~f(void)
            {
                ::FreeLibrary( l );
            }
        } t;
    Then I construct it something like

    Code:
    t( TEXT("H:\\d3dx9d_31.dll"), "D3DXMatrixTranslation", "D3DXMatrixPerspectiveFovLH" )
    XD3DXMatrixTranslation and XD3DXMatrixPerspectiveFovLH are static class fields and usage of the class kind of depends on them. Oh wait, I just realized, the exception would fall through and the construction of the object would fail and I would be able to deal with things. I think that's good. Okay good.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> I just realized, the exception would fall through and the construction of the object would fail and I would be able to deal with things.

    That's how the handling of the exception works, but the issue is still about what to do with resources that have already been acquired when an exception is thrown inside the constructor. In your example, both times you throw std::exception(), ::FreeLibrary(l) will never be called. This might be ok, as in the second throw where apparently the call to LoadLibrary failed. However, the first throw inside the nested if looks like FreeLibrary should be called.

    A simple RAII class should be created just for the call to LoadLibrary and FreeLibrary.

    BTW, the t at the end of the struct declaration is probably not needed, and if you really did want an instance of your struct in that scope you should declare it separately to be more clear. As is it is a different instance than the one you construct with the constructor.

  6. #6
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    C++ should really allow aggregate and array initializers in the initializer list. And also, they should allow variable length template parameter lists. Okay, so this is safe?

    Code:
        struct Library
        {
            HMODULE lib;
    
            Library( LPCTSTR szlib )
            {
                lib = ::LoadLibrary(szlib);
    
                if( !lib )
                {
                    throw std::exception();
                }
            }
    
            operator HMODULE ()
            {
                return lib;
            }
    
            ~Library( void )
            {
                ::FreeLibrary( lib );
            }
        };
    
        template <typename T, typename U>
    
        struct Stuff
        {
            Library l;
    
            Stuff( LPCTSTR lib, LPCSTR foo, LPCSTR bar, T * t, U * u ) 
                : l(lib)
            {
                *t = reinterpret_cast
                    <D3DMATRIX * ( WINAPI * )(D3DMATRIX *, float, float, float)>
                        ( ::GetProcAddress( l, foo ) );
    
                *u = reinterpret_cast
                    <D3DMATRIX * ( WINAPI * )( D3DMATRIX *, float, float, float, float )>
                        ( ::GetProcAddress( l, bar ) );
    
                if( !*t || !*u ) 
                    throw std::exception();
            }
        };

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Okay, so this is safe?
    As far as the automatic call to FreeLibrary happening whenever necessary, it looks safe to me. You could also initialize the Library struct's lib member in an intializer list for consistency, although it really doesn't matter.

    >> C++ should really allow aggregate and array initializers in the initializer list.
    I think they're trying to get that into the next standard.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    > And also, they should allow variable length template parameter lists.

    http://www.osl.iu.edu/~dgregor/cpp/v...templates.html


    The code is safe, though you might want to throw something more expressive than a std::exception().
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    That is way cool. Thank you peoples.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Exception handling in a large project
    By EVOEx in forum C++ Programming
    Replies: 7
    Last Post: 01-25-2009, 07:33 AM
  2. exception handling
    By coletek in forum C++ Programming
    Replies: 2
    Last Post: 01-12-2009, 05:28 PM
  3. Handle C++ exception and structured exception together
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 01-24-2008, 09:21 PM
  4. Signal and exception handling
    By nts in forum C++ Programming
    Replies: 23
    Last Post: 11-15-2007, 02:36 PM
  5. Problem with the exception class in MINGW
    By indigo0086 in forum C++ Programming
    Replies: 6
    Last Post: 01-20-2007, 01:12 PM