How to deallocate memory when handling exception

Discussion in 'C++' started by Tony Johansson, Aug 13, 2005.

  1. Hello Experts!

    Assume foo is a method in a some class or a stand-alone function and method
    push is throwing an exception of class logic_error.
    Assume also that I want to handle this exception in foo if it's possible.
    This will cause a problem because C++ doesn't have the finally keyword and I
    can't do delete both in the exception handler and after the exception
    handler that's because I have put in the throw to throw it further
    to let some other method to handle it. But if I remove this throw how is it
    then possible to get a
    solution that will hold and i a good solution. If I just remove this throw
    and an exception occurs will this cause delete s two times and resuting in
    undefined behaviour.

    void foo()
    {
    IntStack* s

    try
    {
    s = new IntStack(20);
    s->push(20);
    }
    catch(const logic_error& e)
    {
    delete s;
    throw; //
    }

    delete s;
    }

    Many thanks

    //Tony
    Tony Johansson, Aug 13, 2005
    #1
    1. Advertising

  2. Tony Johansson wrote:
    > Hello Experts!
    >
    > Assume foo is a method in a some class or a stand-alone function and method
    > push is throwing an exception of class logic_error.
    > Assume also that I want to handle this exception in foo if it's possible.
    > This will cause a problem because C++ doesn't have the finally keyword and I
    > can't do delete both in the exception handler and after the exception
    > handler that's because I have put in the throw to throw it further
    > to let some other method to handle it. But if I remove this throw how is it
    > then possible to get a
    > solution that will hold and i a good solution. If I just remove this throw
    > and an exception occurs will this cause delete s two times and resuting in
    > undefined behaviour.
    >
    > void foo()
    > {
    > IntStack* s;

    Note that s is uninitialized - could contain garbage.
    >
    > try
    > {
    > s = new IntStack(20);

    new can throw badalloc - s may not get set - still contains garbage.
    > s->push(20);
    > }
    > catch(const logic_error& e)
    > {
    > delete s;
    > throw; //
    > }
    >
    > delete s;


    Trying to delete garbage. Not good 10 out of 10.

    Another problem, is if push throws some other (possibly future)
    exception type, you will leak s.

    > }


    To answer the OP question, I would use the RAII idion (Resource
    Aquisition Is Initialization) and remove the need to handle this type of
    logic manually.

    #include <list>
    #include <memory>

    typedef std::list<int> IntStack;
    struct logic_error {};

    void foo()
    {
    std::auto_ptr<IntStack> s;

    try
    {
    s.reset( new IntStack(20) );
    s->push_back(20);
    }
    catch(const logic_error& e)
    {
    throw; //
    }

    }

    OK - so you don't like that ? This will work too. Although, the code
    above looks alot simpler and much more intuitive.

    void foo()
    {
    IntStack* s = 0;

    try
    {
    try
    {
    s = new IntStack(20);
    s->push(20);
    }
    catch(const logic_error& e)
    {
    delete s;
    s = 0;
    if ( cant_fix_logic )
    {
    throw; //
    }
    }
    } catch (...)
    {
    delete s;
    throw;
    }

    delete s;
    }
    Gianni Mariani, Aug 13, 2005
    #2
    1. Advertising

  3. Tony Johansson

    Pete Becker Guest

    Gianni Mariani wrote:
    >
    >
    > To answer the OP question, I would use the RAII idion (Resource
    > Aquisition Is Initialization) and remove the need to handle this type of
    > logic manually.
    >
    > std::auto_ptr<IntStack> s;
    >


    Just to underscore the point: this is exactly what auto_ptr was designed
    for.

    --

    Pete Becker
    Dinkumware, Ltd. (http://www.dinkumware.com)
    Pete Becker, Aug 13, 2005
    #3
  4. Tony Johansson

    Old Wolf Guest

    Gianni Mariani wrote:
    > Tony Johansson wrote:
    >> void foo()
    >> {
    >> IntStack* s;
    >>
    >> try
    >> {
    >> s = new IntStack(20);
    >> s->push(20);
    >> }
    >> catch(const logic_error& e)
    >> {
    >> delete s;
    >> throw; //
    >> }
    >>
    >> delete s;

    >
    > #include <list>
    > #include <memory>
    >
    > typedef std::list<int> IntStack;
    > struct logic_error {};
    >
    > void foo()
    > {
    > std::auto_ptr<IntStack> s;
    >
    > try
    > {
    > s.reset( new IntStack(20) );
    > s->push_back(20);
    > }
    > catch(const logic_error& e)
    > {
    > throw; //
    > }
    >
    > }
    >
    > OK - so you don't like that ? This will work too. Although, the code
    > above looks alot simpler and much more intuitive.


    Equivalent and even simpler:

    void foo()
    {
    IntStack s(20);
    s.push_back(20);
    }

    Remarkably, your code does the first 2 things listed on the
    'pet peeves' thread on c.l.c++.moderated, ie. using 'new'
    and 'delete' instead of creating an automatic object,
    and catching something only to rethrow it.
    Old Wolf, Aug 13, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric Lilja
    Replies:
    2
    Views:
    3,589
    Victor Bazarov
    Mar 14, 2005
  2. Replies:
    20
    Views:
    1,349
    Heiko Wundram
    May 12, 2006
  3. Replies:
    2
    Views:
    340
    Ron Natalie
    Apr 3, 2008
  4. pereges
    Replies:
    6
    Views:
    299
    santosh
    Jul 7, 2008
  5. alessio211734

    handle deallocate memory on return

    alessio211734, Jun 30, 2009, in forum: C++
    Replies:
    3
    Views:
    558
    Thomas J. Gritzan
    Jul 3, 2009
Loading...

Share This Page