Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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'.

share|improve this question
12  
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 May 9 '13 at 20:11
7  
Separating workflow from cleanup! Hmm, that's a syntactic notion. The workflow is here, but the cleanup is way over there. Why don't we apply this to semicolons. Why do I have to close semicolons in the same code which opened them? If we put the closing semicolons into the destructor, the code will be so much better organized, not having all that syntactic cleanup cluttering the main semicolon-opening action. –  Kaz May 9 '13 at 21:22
2  
4  
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. –  Josh Kelley May 9 '13 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 May 12 '13 at 7:40

5 Answers 5

up vote 35 down vote accepted

As some additional commentary on @Nemanja's answer (which, since it quotes Stroustrup, is really about as good of an answer as you can get):

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 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.

share|improve this answer
6  
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. –  Robert Harvey May 9 '13 at 19:16
12  
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. –  Mason Wheeler May 9 '13 at 20:56
10  
@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. –  Josh Kelley May 9 '13 at 21:01
5  
@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 May 9 '13 at 21:56
6  
@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 May 10 '13 at 1:45

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.

share|improve this answer
5  
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 May 9 '13 at 17:26
18  
@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. –  Nemanja Trifunovic May 9 '13 at 17:33
9  
@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. –  MichaelT May 9 '13 at 17:45
3  
@Mikey Both RAII and finally (as well as some others) are tools for writing code that behaves well in the face of exceptions. Neither the support for finally nor the support for RAII automatically solves this problem. One has to use the respective tool, and use it correctly, to achieve exception safety. Note that the concept of exception safety is language-independent; that it is less widely discussed in other communities may be due to other languages reducing the problem by managing some resources automatically or the programmers being less paranoid. –  delnan May 9 '13 at 18:16
13  
@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 May 10 '13 at 9:13

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.

share|improve this answer
2  
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 May 9 '13 at 17:39
9  
@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. –  Bart van Ingen Schenau May 9 '13 at 18:01
2  
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 May 9 '13 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 May 9 '13 at 20:46
8  
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. –  Steven Burnap May 10 '13 at 2: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.

share|improve this answer
    
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.) –  Thomas Eding Sep 22 at 20:56

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.

share|improve this answer
    
This does not answer the question, and simply proves that finally isn't such a bad idea after all... –  Vector May 9 '13 at 21:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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