Thread: New to exception handling, bad_alloc syntax error.

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    1

    New to exception handling, bad_alloc syntax error.

    Hi there

    I was using this code in my program:

    Code:
    Base *ptr = new Base(para1, para2);
    
    v.push_back( ptr );
    And it was working fine.

    Then I read how I should check for errors in case the 'new' memory could be gained, so changed my code to this:

    Code:
    try
    {
          Base *ptr = new Base(para1, para2);
    }
    catch (bad_alloc& ba)
    {
          cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    v.push_back( ptr );
    But now it fails to compile. Reports :

    'ptr' : undeclared identifier
    I tried removing the curly braces around "Base *ptr = new Base(para1, para2);" but then the compiler(Visual Studio 08 Express) complained that they weren't there. I thought perhaps it was a scope problem.


    Can anyone point out what is wrong with it?

    Thanks very much!


    EDIT - I did use
    #include <new>
    BTW.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The problem is that ptr only exists within the try block. You need to do something like this:
    Code:
    Base* ptr;
    try
    {
        ptr = new Base(para1, para2);
        v.push_back(ptr);
    }
    catch (bad_alloc& ba)
    {
        cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    Or more simply:
    Code:
    try
    {
        v.push_back(new Base(para1, para2));
    }
    catch (bad_alloc& ba)
    {
        cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    The latter solution is better, as push_back can throw bad_alloc as well.

    (edit: ah, wait, you had the push_back in the try blocks at both sides. Never mind that then. Though I still prefer the latter solution. But in the first case you can just use this as well:
    Code:
    try
    {
        Base* ptr = new Base(para1, para2);
        v.push_back(ptr);
    }
    catch (bad_alloc& ba)
    {
        cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    )

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Here the problem seems to be that in case push_back indeed throws, you cannot avoid leaking ptr.

    In general, dumb pointers and exceptions don't go well hand in hand. I'd rather suggest using std::tr1::shared_ptr or boost::shared_ptr (and probably not worrying about catching bad_alloc this close to the allocation)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by anon
    Here the problem seems to be that in case push_back indeed throws, you cannot avoid leaking ptr.
    I suppose you could, e.g.,
    Code:
    Base* ptr = 0;
    try
    {
        ptr = new Base(para1, para2);
        v.push_back(ptr);
    }
    catch (bad_alloc& ba)
    {
        delete ptr;
        cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    And finally, to perfect the code, isn't it wise to use "const bad_alloc &"? I suppose the compiler might be able to optimize out the copy but I doubt it usually does that.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by laserlight View Post
    I suppose you could, e.g.,
    Code:
    Base* ptr = 0;
    try
    {
        ptr = new Base(para1, para2);
        v.push_back(ptr);
    }
    catch (bad_alloc& ba)
    {
        delete ptr;
        cerr << "bad_alloc caught: " << ba.what() << endl;
    }
    That only works if the exception originates from the push_back call. Otherwise you have an invalid delete. A smart pointer is really the best solution, IMO.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by EVOEx
    And finally, to perfect the code, isn't it wise to use "const bad_alloc &"? I suppose the compiler might be able to optimize out the copy but I doubt it usually does that.
    I prefer to use the const, but it should not make a difference in whether a copy is made at the throw, as far as I know.

    Quote Originally Posted by Sebastiani
    That only works if the exception originates from the push_back call. Otherwise you have an invalid delete.
    I do not see how that is the case. I do assume that push_back will only throw std::bad_alloc, but one need not make that assumption, although it might be a requirement of push_back.

    Quote Originally Posted by Sebastiani
    A smart pointer is really the best solution, IMO.
    Of course, unless one should actually store Base objects instead of Base pointers.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by Sebastiani View Post
    That only works if the exception originates from the push_back call. Otherwise you have an invalid delete. A smart pointer is really the best solution, IMO.
    Are you forgetting that you can call delete on a NULL pointer?
    bit∙hub [bit-huhb] n. A source and destination for information.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by laserlight View Post
    I do not see how that is the case. I do assume that push_back will only throw std::bad_alloc, but one need not make that assumption, although it might be a requirement of push_back.
    Quote Originally Posted by bithub
    Are you forgetting that you can call delete on a NULL pointer?
    Ah, right - I had neglected the fact that the pointer was already initialized to NULL. Sorry.

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Wrapping a call to new in a try block sort of misses the point of exception handling. The point is to NOT have to check for errors everywhere they might occur.

    By catching the exception at the lowest possible level, you are making it impossible for the surrounding program code to know about the exception's existence. What will your function do when it gets this exception? Return an error code? Now you've transformed exception handling into return code checking, which is exactly what exception were designed to AVOID.

    You should catch exceptions at the HIGHEST possible level. Hell, for bad_alloc I sometimes don't bother catching the exception at all. If you run out of memory, there isn't a whole lot you can do about it anyway.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Good point. So using the raw allocation it really should be:

    Code:
    Base* ptr = 0;
    try
    {
        ptr = new Base(para1, para2);
        v.push_back(ptr);
    }
    catch (...)
    {
        delete ptr;
        throw;
    }
    Of course, by using a smart pointer the try/catch block can be done away with altogether...

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Sebastiani View Post
    Of course, by using a smart pointer the try/catch block can be done away with altogether...
    And I'd highly recommend it. IMHO, performing manual cleanup in catch{} blocks is the wrong approach. Let RAII handle resource cleanup. The catch{} block should be where you decide how to recover from the exception, not cleaning up the mess.

    Exception safety is built from the ground up.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    The (not-so) funny thing is, RAII seems to be such a poorly-covered subject in programming courses that it's almost an uphill battle when students come here to ask questions. It's really frustrating.

  15. #15
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by Sebastiani View Post
    The (not-so) funny thing is, RAII seems to be such a poorly-covered subject in programming courses that it's almost an uphill battle when students come here to ask questions. It's really frustrating.
    Tell me about it :P. I used these constructs for mutexes over and over and over again. Until it became a pain in the ass and I wrote a class wrapper for that, that locks a mutex and unlocks it always when the object runs out of scope.
    It's very useful, but in these cases I'm not sure it would be much better than the last version...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. PlaySound
    By cangel in forum C++ Programming
    Replies: 16
    Last Post: 10-08-2009, 05:29 PM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. Linking error
    By DockyD in forum C++ Programming
    Replies: 10
    Last Post: 01-20-2003, 05:27 AM