The 'finally' debate

Discussion in 'C++' started by Stefan Arentz, Sep 21, 2004.

  1. I was just reading through some old articles in the 'Why not develop new
    language' thread and came across the finally debate.

    Everytime I mention 'finally' to C++ programmers I get almost emotional
    responses about why it is not needed in C++. I don't get that.

    For example, consider the following code. Please note, I can only use
    heap allocated objects in my current project (new/delete).

    //
    // Foo - Tries to foo. Can throw a FooException
    //

    void Foo()
    {
    try {
    // Do your foo business that could throw a FooException
    }

    catch (...) {
    // Cleanup your business
    throw;
    }

    // Cleanup your business
    }

    Now, with finally I could do this:

    void Foo()
    {
    try {
    // Do your foo business that could throw a FooException
    }

    finally {
    // Cleanup your business
    }
    }

    Which I find *much* cleaner than the other example as there is no
    need to do the cleanup twice.

    Anyway, the debate is useless because we don't have finally. So my question
    really is, how do people refactor the above to something nicer?

    S.
    Stefan Arentz, Sep 21, 2004
    #1
    1. Advertising

  2. "Stefan Arentz" <> wrote in message
    news:...
    >
    > I was just reading through some old articles in the 'Why not develop new
    > language' thread and came across the finally debate.
    >
    > Everytime I mention 'finally' to C++ programmers I get almost emotional
    > responses about why it is not needed in C++. I don't get that.
    >
    > For example, consider the following code. Please note, I can only use
    > heap allocated objects in my current project (new/delete).
    >
    > //
    > // Foo - Tries to foo. Can throw a FooException
    > //
    >
    > void Foo()
    > {
    > try {
    > // Do your foo business that could throw a FooException
    > }
    >
    > catch (...) {
    > // Cleanup your business
    > throw;
    > }
    >
    > // Cleanup your business
    > }
    >
    > Now, with finally I could do this:
    >
    > void Foo()
    > {
    > try {
    > // Do your foo business that could throw a FooException
    > }
    >
    > finally {
    > // Cleanup your business
    > }
    > }
    >
    > Which I find *much* cleaner than the other example as there is no
    > need to do the cleanup twice.
    >
    > Anyway, the debate is useless because we don't have finally. So my

    question
    > really is, how do people refactor the above to something nicer?
    >


    Simple use a class with a destructor (it's because Java doesn't have
    destructors that it needs finally)

    void Foo()
    {
    FooBusiness biz;
    // Do your foo business that could throw a FooException
    }

    The FooBusiness destructor does the cleanup. This way you do not even need a
    try/catch

    john
    John Harrison, Sep 21, 2004
    #2
    1. Advertising

  3. "Stefan Arentz" <> skrev i en meddelelse
    news:...
    >

    [snip]
    > Which I find *much* cleaner than the other example as there is no
    > need to do the cleanup twice.
    >
    > Anyway, the debate is useless because we don't have finally. So my

    question
    > really is, how do people refactor the above to something nicer?
    >
    > S.


    Hi Stefan

    John Harrison has already answered your question. I just want to add that
    you could check out boost for some of the smart pointers there. There is
    also "scopeguard" for more special stuff.

    /Peter
    Peter Koch Larsen, Sep 21, 2004
    #3
  4. "John Harrison" <> writes:

    > Simple use a class with a destructor (it's because Java doesn't have
    > destructors that it needs finally)
    >
    > void Foo()
    > {
    > FooBusiness biz;
    > // Do your foo business that could throw a FooException
    > }
    >
    > The FooBusiness destructor does the cleanup. This way you do not even need a
    > try/catch


    but what's about this:

    void bar()
    {
    char * my_ptr;
    try
    {
    SomeObject instace;
    my_ptr = new char[987];
    // do something
    instace.doSomehting() // throws an exception let's say MyExec
    // work with pointer
    delete my_ptr
    }
    catch(MyExec &exc)
    {
    delete my_ptr;
    // error handling
    }
    }

    Here it's necessary to duplicate code, another example would be file
    handling.
    Sometimes a finally - block can help.

    Mayby someone cann tell me why this was not taken into C++

    Kind regards,
    Nicolas

    --
    | Nicolas Pavlidis | Elvis Presly: |\ |__ |
    | Student of SE & KM | "Into the goto" | \|__| |
    | | ICQ #320057056 | |
    |-------------------University of Technology, Graz----------------|
    Nicolas Pavlidis, Sep 21, 2004
    #4
  5. "Peter Koch Larsen" <> writes:

    > "Stefan Arentz" <> skrev i en meddelelse
    > news:...
    > >

    > [snip]
    > > Which I find *much* cleaner than the other example as there is no
    > > need to do the cleanup twice.
    > >
    > > Anyway, the debate is useless because we don't have finally. So my

    > question
    > > really is, how do people refactor the above to something nicer?
    > >
    > > S.

    >
    > Hi Stefan
    >
    > John Harrison has already answered your question. I just want to add that
    > you could check out boost for some of the smart pointers there. There is
    > also "scopeguard" for more special stuff.


    I'm on a device that is too small to even include STL :)

    S.
    Stefan Arentz, Sep 21, 2004
    #5
  6. "John Harrison" <> writes:

    ....

    > Simple use a class with a destructor (it's because Java doesn't have
    > destructors that it needs finally)
    >
    > void Foo()
    > {
    > FooBusiness biz;
    > // Do your foo business that could throw a FooException
    > }
    >
    > The FooBusiness destructor does the cleanup. This way you do not even need a
    > try/catch


    I don't buy this for two reasons.

    Wrapper classes introduce more code. I would like to use less code. I also
    think it is a workaround and not a structural solution.

    The above would simply move the exception handling and my finally problem
    to a different place but it would still be present. I like it that you as
    a user of the class don't have to deal with it anymore, but that is more
    visual/convenience.

    S.
    Stefan Arentz, Sep 21, 2004
    #6
  7. * Nicolas Pavlidis:
    >
    > but what's about this:
    >
    > void bar()
    > {
    > char * my_ptr;
    > try
    > {
    > SomeObject instace;
    > my_ptr = new char[987];
    > // do something
    > instace.doSomehting() // throws an exception let's say MyExec
    > // work with pointer
    > delete my_ptr
    > }
    > catch(MyExec &exc)
    > {
    > delete my_ptr;
    > // error handling
    > }
    > }



    void bar()
    {
    std::vector<char> my_ptr( 987 );
    // do something
    instace.doSomehting(); // semicolon here
    }



    > Here it's necessary to duplicate code


    Nope.


    > another example would be file handling.


    Nope.


    > Sometimes a finally - block can help.


    Yes.


    > Mayby someone cann tell me why this was not taken into C++


    Because 'finally' is rarely needed in C++, and where it is needed it
    indicates a redesign/refactoring is called for, and in the extremely
    rare cases where that isn't an option, you can easily emulate it.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Sep 21, 2004
    #7
  8. (Alf P. Steinbach) writes:

    ....

    > > Mayby someone cann tell me why this was not taken into C++

    >
    > Because 'finally' is rarely needed in C++, and where it is needed it
    > indicates a redesign/refactoring is called for, and in the extremely
    > rare cases where that isn't an option, you can easily emulate it.


    So how do you emulate it.

    In my situation: no templates, no STL, no external libraries. Just bare
    C++. GCC extensions are acceptable (3.3).

    I've used inner functions (GCC extension) at one point.

    void Foo()
    {
    vars;

    void cleanup() {
    cleanup vars;
    }

    try {
    }

    catch (...) {
    cleanup();
    throw;
    }

    cleanup();
    }

    But still, very yuckie :)

    S.
    Stefan Arentz, Sep 21, 2004
    #8
  9. >
    > I'm on a device that is too small to even include STL :)


    If you design your classes with nice d'tors and only use classes
    instead of new/malloc allocations, the problem is void. If you seem to
    have a small device (WTF is this - a fridge?), then write optimized
    code. The 'final' keyword would not do anything else than wrap your
    code in a gargabe collector, which _is_ available as template classes
    for those who cannot remember what they allocate. ;)
    A good compiler will produce smal code from a template library, though
    the source code might be big. And don't tell me you're compiling the
    program _on_ the fride.
    -Gernot
    Gernot Frisch, Sep 21, 2004
    #9
  10. Stefan Arentz

    Tom Widmer Guest

    On 21 Sep 2004 14:32:39 +0200, Stefan Arentz <>
    wrote:

    >
    >I was just reading through some old articles in the 'Why not develop new
    >language' thread and came across the finally debate.
    >
    >Everytime I mention 'finally' to C++ programmers I get almost emotional
    >responses about why it is not needed in C++. I don't get that.
    >
    >For example, consider the following code. Please note, I can only use
    >heap allocated objects in my current project (new/delete).


    So your current project isn't in standard C++, but rather a
    company/personal dialect? I'm not sure we can help much with that...

    >//
    >// Foo - Tries to foo. Can throw a FooException
    >//
    >
    >void Foo()
    >{
    > try {
    > // Do your foo business that could throw a FooException
    > }
    >
    > catch (...) {
    > // Cleanup your business
    > throw;
    > }
    >
    > // Cleanup your business
    >}
    >
    >Now, with finally I could do this:
    >
    >void Foo()
    >{
    > try {
    > // Do your foo business that could throw a FooException
    > }
    >
    > finally {
    > // Cleanup your business
    > }
    >}
    >
    >Which I find *much* cleaner than the other example as there is no
    >need to do the cleanup twice.
    >
    >Anyway, the debate is useless because we don't have finally. So my question
    >really is, how do people refactor the above to something nicer?


    void Foo()
    {
    //Do your foo business that could throw a FooException
    }

    where the foo business uses stack based objects whose destructors do
    the cleanup. If your company doesn't allow that, then your company is
    using mackled C++, and might be better off with C# or Java. At the
    very least you can use std::auto_ptr.

    Tom
    Tom Widmer, Sep 21, 2004
    #10
  11. > In my situation: no templates, no STL, no external libraries. Just
    > bare
    > C++. GCC extensions are acceptable (3.3).


    Beeeeeep!
    No templates but bare C++? That's like "a tree, but without a trunk,
    twigs and leaves". Only the bugs remain...
    Gernot Frisch, Sep 21, 2004
    #11
  12. * Stefan Arentz:
    > (Alf P. Steinbach) writes:
    >
    > ...
    >
    > > > Mayby someone cann tell me why this was not taken into C++

    > >
    > > Because 'finally' is rarely needed in C++, and where it is needed it
    > > indicates a redesign/refactoring is called for, and in the extremely
    > > rare cases where that isn't an option, you can easily emulate it.

    >
    > So how do you emulate it.


    One way: you exit the inner block by throwing an exception so that all exits
    are via exceptions. In the common catch handler you clean up (this is the
    'finally' part) and then check whether the exception corresponds to a normal
    return. If so, you do a normal return, otherwise you rethrow. I think this
    should perhaps be tought in programming classes because it makes the cost of
    'finally', what goes on behind the scenes, very explicit. On the other hand
    there is the risk that what students know about they will use...

    Another way: you pass references to things to be cleaned up to an object of a
    locally declared class where the destructor implements the 'finally'.

    But generally, use smart-pointers, RAII and exception-transparent code to
    avoid the need for 'finally' handling: whenever you find yourself thinking
    that 'finally' would be nice here, think about how much nicer if 'finally'
    weren't needed here at all, i.e. if the code was refactored/redesigned! :eek:)



    PS: No need to use gcc extension to define an inner function; where you
    need it you can use a local class.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Sep 21, 2004
    #12
  13. Stefan Arentz

    Rolf Magnus Guest

    Nicolas Pavlidis wrote:

    > "John Harrison" <> writes:
    >
    >> Simple use a class with a destructor (it's because Java doesn't have
    >> destructors that it needs finally)
    >>
    >> void Foo()
    >> {
    >> FooBusiness biz;
    >> // Do your foo business that could throw a FooException
    >> }
    >>
    >> The FooBusiness destructor does the cleanup. This way you do not even
    >> need a try/catch

    >
    > but what's about this:
    >
    > void bar()
    > {
    > char * my_ptr;
    > try
    > {
    > SomeObject instace;
    > my_ptr = new char[987];
    > // do something
    > instace.doSomehting() // throws an exception let's say MyExec
    > // work with pointer
    > delete my_ptr
    > }
    > catch(MyExec &exc)
    > {
    > delete my_ptr;
    > // error handling
    > }
    > }
    >
    > Here it's necessary to duplicate code, another example would be file
    > handling.


    That's what std::auto_ptr is for:

    void bar()
    {
    try
    {
    SomeObject instace;
    std::auto_ptr<char> my_ptr(new char[987]);
    // do something
    instace.doSomehting() // throws an exception let's say MyExec
    }
    catch(MyExec &exc)
    {
    // error handling
    }
    }

    See? You don't need to cleanup twice. You actually don't need to cleanup at
    all. The destructor does the work for you, and that's how it's supposed to
    be in C++.

    > Sometimes a finally - block can help.


    It rather looks to me like a workaround for a design problem. In most cases,
    you shouldn't need to deal with raw memory (and for those, you have
    auto_ptr). In any other cases, the objects should do the cleanup themselves
    on destruction. This is btw. a big advantage over GC languages that lack a
    destructor (or at least lack one which is called at points that are exactly
    defined)

    > Mayby someone cann tell me why this was not taken into C++


    Probably nobody saw a need for it.
    Rolf Magnus, Sep 21, 2004
    #13
  14. > > The FooBusiness destructor does the cleanup. This way you do not even
    need a
    > > try/catch

    >
    > I don't buy this for two reasons.
    >
    > Wrapper classes introduce more code. I would like to use less code. I also
    > think it is a workaround and not a structural solution.


    Cleanup code are not part of the program logic, so it is very nice to avoid
    it in the middle of the main code by putting it away in a destructor.
    In addition the destructor approach prevents programmers from forgetting
    cleanup code which leads to more stable applications.
    So it is not a workaround but a significant improvement.

    Niels Dybdahl
    Niels Dybdahl, Sep 21, 2004
    #14
  15. Tom Widmer <> writes:

    > On 21 Sep 2004 14:32:39 +0200, Stefan Arentz <>
    > wrote:
    >
    > >
    > >I was just reading through some old articles in the 'Why not develop new
    > >language' thread and came across the finally debate.
    > >
    > >Everytime I mention 'finally' to C++ programmers I get almost emotional
    > >responses about why it is not needed in C++. I don't get that.
    > >
    > >For example, consider the following code. Please note, I can only use
    > >heap allocated objects in my current project (new/delete).

    >
    > So your current project isn't in standard C++, but rather a
    > company/personal dialect? I'm not sure we can help much with that...


    Well, it is code for firmware of a small device. Not very small, but small
    enough that something like STL or Boost is not an option. Templates probably
    are, but I've had no reason to use them yet and I would have to look into
    object code size first.

    Btw, I am very happy with the choise of C++ for this project. It has made
    the code more robust and organized.

    ....

    > >Anyway, the debate is useless because we don't have finally. So my question
    > >really is, how do people refactor the above to something nicer?

    >
    > void Foo()
    > {
    > //Do your foo business that could throw a FooException
    > }
    >
    > where the foo business uses stack based objects whose destructors do
    > the cleanup. If your company doesn't allow that, then your company is
    > using mackled C++, and might be better off with C# or Java. At the
    > very least you can use std::auto_ptr.


    So that would mean stack based objects and references? Get rid of all
    pointers? It would probably mean a complete redesign of some things,
    but I am willing to look into it. Is this the RAII stuff other people
    were talking about?

    S.
    Stefan Arentz, Sep 21, 2004
    #15
  16. "Gernot Frisch" <> writes:

    > >
    > > I'm on a device that is too small to even include STL :)

    >
    > If you design your classes with nice d'tors and only use classes
    > instead of new/malloc allocations, the problem is void. If you seem to
    > have a small device (WTF is this - a fridge?), then write optimized
    > code. The 'final' keyword would not do anything else than wrap your
    > code in a gargabe collector, which _is_ available as template classes
    > for those who cannot remember what they allocate. ;)
    > A good compiler will produce smal code from a template library, though
    > the source code might be big. And don't tell me you're compiling the
    > program _on_ the fride.


    Neh, we keep the beer in the fridge. The device is a MIPS based device
    with not too much RAM/Flash. Think <= 8MB. which needs to be shared
    with a kernel, libraries some tools.

    It is not very special, you just can't use all nice tricks that are
    obvious on a normal 1GB workstation with a standard 80GB drive :)

    S.
    Stefan Arentz, Sep 21, 2004
    #16
  17. Stefan Arentz

    Rolf Magnus Guest

    Stefan Arentz wrote:

    > (Alf P. Steinbach) writes:
    >
    > ...
    >
    >> > Mayby someone cann tell me why this was not taken into C++

    >>
    >> Because 'finally' is rarely needed in C++, and where it is needed it
    >> indicates a redesign/refactoring is called for, and in the extremely
    >> rare cases where that isn't an option, you can easily emulate it.

    >
    > So how do you emulate it.
    >
    > In my situation: no templates, no STL, no external libraries. Just bare
    > C++. GCC extensions are acceptable (3.3).
    >
    > I've used inner functions (GCC extension) at one point.
    >
    > void Foo()
    > {
    > vars;
    >
    > void cleanup() {
    > cleanup vars;
    > }
    >
    > try {
    > }
    >
    > catch (...) {
    > cleanup();
    > throw;
    > }
    >
    > cleanup();
    > }
    >
    > But still, very yuckie :)


    Why don't the destructors of your "vars" do the cleanup? Anyway, you can
    still use RAII:

    void Foo()
    {
    struct whatever
    {
    // your variables

    ~whatever()
    {
    // cleanup
    }
    } vars;

    // something that throws - or not.
    }

    No try, no catch, no finally needed. I admit that finally would be slightly
    more convenient, but in my experience the cases where something like that
    is needed are rare.
    Rolf Magnus, Sep 21, 2004
    #17
  18. Stefan Arentz

    Greg Comeau Guest

    In article <>,
    Stefan Arentz <> wrote:
    >Well, it is code for firmware of a small device. Not very small, but small
    >enough that something like STL or Boost is not an option. Templates probably
    >are, but I've had no reason to use them yet and I would have to look into
    >object code size first.


    Are you actually aware of a constraint using STL or Boost will
    impose upon you, or are you just assuming they will? It might
    be worth actually seeing which parts are acceptable. You may
    also find something like Dinkumware's embedded STL extensions
    a practical compromise.
    --
    Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
    Greg Comeau, Sep 21, 2004
    #18
  19. Stefan Arentz

    Jeff Flinn Guest

    "Stefan Arentz" <> wrote in message
    news:...
    > Tom Widmer <> writes:
    >
    > > On 21 Sep 2004 14:32:39 +0200, Stefan Arentz <>
    > > wrote:
    > >
    > > >
    > > >I was just reading through some old articles in the 'Why not develop

    new
    > > >language' thread and came across the finally debate.
    > > >
    > > >Everytime I mention 'finally' to C++ programmers I get almost emotional
    > > >responses about why it is not needed in C++. I don't get that.
    > > >
    > > >For example, consider the following code. Please note, I can only use
    > > >heap allocated objects in my current project (new/delete).

    > >
    > > So your current project isn't in standard C++, but rather a
    > > company/personal dialect? I'm not sure we can help much with that...

    >
    > Well, it is code for firmware of a small device. Not very small, but small
    > enough that something like STL or Boost is not an option. Templates

    probably

    Is this because your compiler doesn't support STL/Boost? Or that you "think"
    STL\Boost will require more memory?

    Jeff F
    Jeff Flinn, Sep 21, 2004
    #19
  20. "Stefan Arentz" <> skrev i en meddelelse
    news:...
    > "Peter Koch Larsen" <> writes:
    >
    > > "Stefan Arentz" <> skrev i en meddelelse
    > > news:...
    > > >

    > > [snip]
    > > > Which I find *much* cleaner than the other example as there is no
    > > > need to do the cleanup twice.
    > > >
    > > > Anyway, the debate is useless because we don't have finally. So my

    > > question
    > > > really is, how do people refactor the above to something nicer?
    > > >
    > > > S.

    > >
    > > Hi Stefan
    > >
    > > John Harrison has already answered your question. I just want to add

    that
    > > you could check out boost for some of the smart pointers there. There is
    > > also "scopeguard" for more special stuff.

    >
    > I'm on a device that is too small to even include STL :)
    >
    > S.


    I do not understand what you're saying. STL - or templates - does not
    necessarily use more ressources than handwritten code. In your case it
    should be safe.

    /Peter
    Peter Koch Larsen, Sep 21, 2004
    #20
    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. =?Utf-8?B?UGF1bA==?=

    Eternal Debate: Cookies vs. Sessions vs. QueryString

    =?Utf-8?B?UGF1bA==?=, Dec 9, 2005, in forum: ASP .Net
    Replies:
    6
    Views:
    4,668
    m.posseth
    Dec 12, 2005
  2. Christian Bongiorno
    Replies:
    5
    Views:
    531
    Chris Uppal
    Aug 30, 2004
  3. Christian Bongiorno
    Replies:
    1
    Views:
    333
    Chris Uppal
    Sep 27, 2004
  4. Christian Bongiorno

    More Inner class debate

    Christian Bongiorno, Sep 28, 2004, in forum: Java
    Replies:
    2
    Views:
    354
    P.Hill
    Sep 29, 2004
  5. David Lozzi

    Try...Catch...Finally not firing finally?

    David Lozzi, Apr 23, 2007, in forum: ASP .Net
    Replies:
    12
    Views:
    783
    Alvin Bruney [MVP]
    May 11, 2007
Loading...

Share This Page