70

Exception handling in C++ is limited to try/throw/catch. Unlike Object Pascal, Java, C# and Python, even in C++ 11, the finally construct has not been implemented.

I have seen an awful lot of C++ literature discussing "exception safe code". Lippman writes that exception safe code is an important but advanced, difficult topic, beyond the scope of his Primer - which seems to imply that safe code is not fundamental to C++. Herb Sutter devotes 10 chapters to the topic in his Exceptional C++ !

Yet it seems to me that many of the problems encountered when attempting to write "exception safe code" could be quite well solved if the finally construct was implemented, allowing the programmer to ensure that even in the event of an exception, the program can be restored to a safe, stable, leak-free state, close to the point of allocation of resources and potentially problematic code. As a very experienced Delphi and C# programmer I use try.. finally blocks quite extensively in my code, as do most programmers in these languages.

Considering all the 'bells and whistles' implemented in C++ 11, I was astonished to find that 'finally' was still not there.

So, why has the finally construct never been implemented in C++? It's really not a very difficult or advanced concept to grasp and goes a long ways towards helping the programmer to write 'exception safe code'.

20
  • 27
    Why no finally? Because you release things in the destructor which fires automatically when the object (or smart pointer) leaves scope. Destructors are superior to finally{} since it separates workflow from cleanup logic. Just as you wouldn't want calls to free() cluttering up your workflow in a garbage collected language.
    – mike30
    Commented May 9, 2013 at 20:11
  • 2
  • 8
    Asking the question, "Why is there no finally in C++, and what techniques for exception handling are used in its place?" is valid and on topic for this site. The existing answers cover this well, I think. Turning it into a discussion on "Are the C++ designers' reasons for not including finally worthwhile?" and "Should finally be added to C++?" and carrying on the discussion across comments on the question and every answer doesn't fit the model of this Q&A site. Commented May 9, 2013 at 21:31
  • 2
    If you have finally, you already have separation of concerns: the main code block is here, and the cleanup concern is taken care of here.
    – Kaz
    Commented May 12, 2013 at 7:40
  • 2
    @Kaz. The difference is implicit vs explicit clean up. A destructor gives you automatic clean up similar to how a plain old primitive is cleaned up as it pops off the stack. You don't need to make any explicit clean up calls and can focus on your core logic. Imagine how convoluted it would be if you had to clean up stack allocated primitives in a try/finally. Implicit clean up is superior. The comparison of class syntax to anonymous functions is not relevant. Although by passing first class functions to a function which releases a handle could centralize manual cleanup.
    – mike30
    Commented May 15, 2013 at 13:19

7 Answers 7

66

It's really just a matter of understanding the philosophy and idioms of C++. Take your example of an operation that opens a database connection on a persistent class and has to make sure that it closes that connection if an exception is thrown. This is a matter of exception safety and applies to any language with exceptions (C++, C#, Delphi...).

In a language that uses try / finally, the code might look something like this:

database.Open();
try {
    database.DoRiskyOperation();
} finally {
    database.Close();
}

Simple and straightforward. There are, however, a few disadvantages:

  • If the language doesn't have deterministic destructors, I always have to write the finally block, otherwise I leak resources.
  • If DoRiskyOperation is more than a single method call - if I have some processing to do in the try block - then the Close operation can end up being a decent bit away from the Open operation. I can't write my cleanup right next to my acquisition.
  • If I have several resources that need to be acquired then freed in an exception-safe manner, I can end up with several layers deep of try / finally blocks.

The C++ approach would look like this:

ScopedDatabaseConnection scoped_connection(database);
database.DoRiskyOperation();

This completely solves all of the disadvantages of the finally approach. It has a couple of disadvantages of its own, but they're relatively minor:

  • There's a good chance you need to write the ScopedDatabaseConnection class yourself. However, it's a very simple implementation - only 4 or 5 lines of code.
  • It involves creating an extra local variable - which you're apparently not a fan of, based on your comment about "constantly creating and destroying classes to rely on their destructors to clean up your mess is very poor" - but a good compiler will optimize out any of the extra work that an extra local variable involves. Good C++ design relies a lot on these sorts of optimizations.

Personally, considering these advantages and disadvantages, I find RAII (Resource Acquisition Is Initialization) a much preferable technique to finally. Your mileage may vary.

Finally, because RAII is such a well-established idiom in C++, and to relieve developers of some of the burden of writing numerous Scoped... classes, there are libraries like ScopeGuard and Boost.ScopeExit that facilitate this sort of deterministic cleanup.

19
  • 9
    C# has the using statement, which automatically cleans up any object implementing the IDisposable interface. So while it's possible to get it wrong, it's pretty easy to get it right. Commented May 9, 2013 at 19:16
  • 25
    Having to write an entirely new class to take care of temporary state change reversal, using a design idiom that is implemented by the compiler with a try/finally construct because the compiler does not expose a try/finally construct and the only way to access it is through the class-based design idiom, is not an "advantage;" it's the very definition of an abstraction inversion. Commented May 9, 2013 at 20:56
  • 23
    @MasonWheeler - Umm, I didn't say that having to write a new class is an advantage. I said it's a disadvantage. On the balance, though, I prefer RAII to having to use finally. Like I said, your mileage may vary. Commented May 9, 2013 at 21:01
  • 9
    @JoshKelley: 'Good C++ design relies a lot on these sorts of optimizations.' Writing gobs of extraneous code and then relying on compiler optimization is Good Design?! IMO it's the antithesis of good design. Among the fundamentals of good design is concise, easily readable code. Less to debug, less to maintain, etc etc etc. You should NOT be writing gobs of code and then relying on the compiler to make it all go away - IMO that makes no sense at all!
    – Vector
    Commented May 9, 2013 at 21:56
  • 22
    @Mikey: So duplicating cleanup code (or the fact that cleanup must happen) all over the code-base is "concise" and "easily readable"? With RAII, you write such code once, and it is automatically applied everywhere.
    – Mankarse
    Commented May 10, 2013 at 1:45
62

From Why doesn't C++ provide a "finally" construct? in Bjarne Stroustrup's C++ Style and Technique FAQ:

Because C++ supports an alternative that is almost always better: The "resource acquisition is initialization" technique (TC++PL3 section 14.4). The basic idea is to represent a resource by a local object, so that the local object's destructor will release the resource. That way, the programmer cannot forget to release the resource.

27
  • 8
    But there's nothing about that technique that's specific to C++, is there? You can do RAII in any language with objects, constructors and destructors. It's a great technique, but RAII merely existing doesn't imply that a finally construct is always useless forever and ever, despite what Strousup is saying. The mere fact that writing "exception safe code" is a big deal in C++ is proof of that. Heck, C# has both destructors and finally, and they both get used.
    – Tacroy
    Commented May 9, 2013 at 17:26
  • 30
    @Tacroy: C++ is one of very few mainstream languages that has deterministic destructors. C# "destructors" are useless for this purpose, and you need to manually write "using" blocks to have RAII. Commented May 9, 2013 at 17:33
  • 17
    @Mikey you have the answer of "Why doesn't C++ provide a "finally" construct?" directly from Stroustrup himself there. What more could you ask for? That is why.
    – user40980
    Commented May 9, 2013 at 17:45
  • 5
    @Mikey If you worry about your code behaving well, in particular not leaking resources, when exceptions are thrown at it, you are worrying about exception safety/trying to write exception safe code. You're just not calling it that, and due to different tools being available you implement it differently. But it's exactly what C++ people talk about when they discuss exception safety.
    – user7043
    Commented May 9, 2013 at 18:22
  • 21
    @Kaz: I only need to remember to do the cleanup in the destructor once, and from then on I just use the object. I need to remember to do the cleanup in the finally block every time I use the operation that allocates.
    – deworde
    Commented May 10, 2013 at 9:13
21

The reason that C++ does not have finally is because it is not needed in C++. finally is used to execute some code regardless of whether an exception has occurred or not, which almost always is some kind of cleanup code. In C++, this cleanup code should be in the destructor of the relevant class and the destructor will always be called, just like a finally block. The idiom of using the destructor for your cleanup is called RAII.

Within the C++ community there might be more talk about 'exception safe' code, but it is almost equally important in other languages that have exceptions. The whole point of 'exception safe' code is that you think about in what state your code gets left if an exception occurs in any of the functions/methods that you call.
In C++, 'exception safe' code is slightly more important, because C++ does not have automatic garbage collection that takes care of objects that are left orphaned due to an exception.

The reason the exception safety is discussed more in the C++ community probably also stems from the fact that in C++ you have to be more aware of what can go wrong, because there are fewer default safety nets in the language.

17
  • 3
    Note: Please do not contend that C++ has deterministic destructors. Object Pascal/Delphi also has deterministic destructors yet also supports 'finally', for the very good reasons I explained in my first comments below.
    – Vector
    Commented May 9, 2013 at 17:39
  • 16
    @Mikey: Given that there has never been a proposal to add finally to the C++ standard, I think it is safe to conclude that the C++ community does not deem the absence of finally a problem. Most languages that do have finally lack the consistent deterministic destruction that C++ has. I see that Delphi has them both, but I don't know its history well enough to know which was there first. Commented May 9, 2013 at 18:01
  • 4
    Dephi does not support stack based objects - only heap based, and object references on the stack. Therefore 'finally' is necessary to explicitly invoke destructors etc when appropriate.
    – Vector
    Commented May 9, 2013 at 18:24
  • 2
    There is a whole lot of cruft in C++ that is arguably not needed, so this can't be the right answer.
    – Kaz
    Commented May 9, 2013 at 20:46
  • 16
    In the more than two decades I've used the language, and worked with other people that used the language, I've never encountered a working C++ programmer who said "I really wish the language had a finally". I can't ever recall any task that it would have made easier, had I had access to it.
    – user53141
    Commented May 10, 2013 at 2:15
15

Others have discussed RAII as the solution. It's a perfectly good solution. But that doesn't really address why they didn't add finally as well since it's a widely desired thing. The answer to that is more fundamental to the design and development of C++: throughout the development of C++ those involved have strongly resisted the introduction of design features that can be achieved using other features without a huge amount of fuss and especially where this requires the introduction of new keywords that could render older code incompatible. Since RAII provides a highly functional alternative to finally and you can actually roll your own finally in C++11 anyway, there was little call for it.

All you need to do is create a class Finally that calls the function passed to it's constructor in it's destructor. Then you can do this:

try
{
    Finally atEnd([&] () { database.close(); });

    database.doRisky();
}

Most native C++ programmers will, in general, prefer cleanly designed RAII objects however.

1
  • 4
    You are missing the reference capture in your lambda. Should be Finally atEnd([&] () { database.close(); }); Also, I imagine the following is better: { Finally atEnd(...); try {...} catch(e) {...} } (I lifted the finalizer out of the try-block so it executes after the catch blocks.) Commented Sep 22, 2014 at 20:56
3

You can use a "trap" pattern - even if you don't want to use try/catch block.

Put a simple object in the required scope. In this object's destructor put your "finaly" logic. No matter what, when the stack is unwound, object's destructor will be called and you'll get your candy.

1
  • 2
    This does not answer the question, and simply proves that finally isn't such a bad idea after all...
    – Vector
    Commented May 9, 2013 at 21:47
2

I'm not sure I agree with assertions here that RAII is a superset of finally. The achilles heel of RAII is simple: exceptions. RAII is implemented with destructors, and it's always wrong in C++ to throw out of a destructor. That means that you cannot use RAII when you need your cleanup code to throw. If finally were implemented, on the other hand, there's no reason to believe that it would not be legal to throw from a finally block.

Consider a code path like this:

void foo() {
    try {
        ... stuff ...
        complex_cleanup();
    } catch (A& a) {
        handle_a(a);
        complex_cleanup();
        throw;
    } catch (B& b) {
        handle_b(b);
        complex_cleanup();
        throw;
    } catch (...) {
        handle_generic();
        complex_cleanup();
        throw;
    }
}

If we had finally we could write:

void foo() {
    try {
        ... stuff ...
    } catch (A& a) {
        handle_a(a);
        throw;
    } catch (B& b) {
        handle_b(b);
        throw;
    } catch (...) {
        handle_generic();
        throw;
    } finally {
        complex_cleanup();
    }
}

But there is no way, that I can find, to get the equivalent behavior using RAII.

If someone knows how to do this in C++, I'm very interested in the answer. I'd even be happy with something that relied on, for example, enforcing that all exceptions inherited from a single class with some special capabilities or something.

17
  • 3
    In your second example, if complex_cleanup can throw, then you could have a case where two uncaught exceptions are in flight at once, just as you would with RAII / destructors, and C++ refuses to allow this. If you want the original exception to be seen, then complex_cleanup should prevent any exceptions, just as it would with RAII / destructors. If you want complex_cleanup's exception to be seen, then I think you can use nested try/catch blocks - although this is a tangent and hard to fit into a comment, so it's worth a separate question. Commented Aug 31, 2015 at 1:26
  • 5
    I understand your point - there are some legitimate issues with destructors that might throw - but those are rare. Saying that RAII + exceptions has unresolved issues or that RAII isn't a general-purpose solution simply doesn't match the experience of most C++ developers. Commented Aug 31, 2015 at 12:42
  • 1
    Regarding finally: yes I know exceptions don't nest in C++, but throwing from inside catch is well-defined and does not cause your program to terminate. Certainly a throw from finally would work the same way, and not behave like a throw from a destructor. In cleanup() I want to throw, I want to see the exception, but I don't want to terminate my program. Thus I cannot call it from a destructor, thus I cannot use it with RAII, and thus RAII, while cool, cannot replace finally. Nested try/catch can't help. Destructors are a round peg for an oblong hole. Commented Aug 31, 2015 at 15:52
  • 1
    Using RAII properly, you should not really be calling complex_cleanup() functions. The point of RAII is that the stack is your best cleanup tool - your code does not explicitly handle resource cleanup. BTW, the answer is not that RAII is a superset of finally- the answer is that finally is an unnecessary, clumsy construct that leads to poorly structured code and improper allocation of resources as compared to RAII. I asked this question two years ago, read Stroustrup on RAII after getting the answer, and I have since written a lot of fast,efficient code that has no need for finally.
    – Vector
    Commented Aug 31, 2015 at 23:04
  • 1
    If you find yourself with the need to raise exceptions in destructors, you're doing something wrong - probably using pointers in other places when they're not necessary.
    – Vector
    Commented Sep 1, 2015 at 23:19
2

Well, you could sort of roll-your-own finally, using Lambdas, which would get the following to compile fine (using an example without RAII of course, not the nicest piece of code):

{
    FILE *file = fopen("test","w");

    finally close_the_file([&]{
        cout << "We're closing the file in a pseudo-finally clause." << endl;
        fclose(file);
    });
}

See this article.

Not the answer you're looking for? Browse other questions tagged or ask your own question.