views:

1305

answers:

15

Been doing Java for number of years so haven't been tracking C++. Has finally clause been added to C++ exception handling in the language definition?

Is there a favored idiom that mimics Java's try/finally?

Am also bothered that C++ doesn't have an ultimate super type for all possible exceptions that could be thrown - like Java's Throwable class.

I can write:

try {
  // do something
} catch(...) {
  // alas, can't examine the exception
  // can only do cleanup code and perhaps rethrow, ala:
  throw;
}

ADDENDUM EDIT:

I ended up accepting the answer that had the most up votes, i.e., use destructors to do cleanup. Of course, from my own comments, it is clear I don't entirely agree with that. However, C++ is what it is and so in the application endeavor I have in mind, I'm going to more or less strive to adhere to common community practice. I'll use template classes to wrap resources that don't already have a class destructor (i.e., C library resources), thus bestowing on them destructor semantics.

NEW ADDENDUM EDIT:

Hmm, instead of finally then a closure feature perhaps? A closure combined with ScopeGuard approach (see one of the answers below) would be a way to accomplish cleanup with arbitrary actions and access to the cleanup code's outer scope context. Cleanup could be done in the idiom fashion that is seen in Ruby programming where they supply cleanup blocks when a resource is being opened. Isn't a closure feature being considered for C++?

+21  A: 

By making effective use of destructors. When an exception is thrown in a try block, any object created within it will be destroyed immediately (and hence its destructor called).

This is different from Java where you have no idea when an object's finalizer will be called.

UPDATE: Straight from the horse's mouth: Why doesn't C++ provide a "finally" construct?

Jason Baker
In Java, you don't even know **if** an object's finalizer will be called. The JVM calls finalizers on a "best effort" basis.
j_random_hacker
Is better to avoid finalizers altogether - at least certainly on a general basis. They're a performance problem for the garbage collector. Obviously we've learned to write a lot of successful and robust 24/7 server code without depending on any manner of destructor-like construct.
RogerV
I ended up accepting this answer, i.e., use destructors to do cleanup. Of course, from my own comments, it is clear I don't entirely agree with that. However, C++ is what it is and so in the application endeavor I have in mind, I'm going to more or less strive to adhere to common community practice.
RogerV
+10  A: 

C++'s answer is RAII: The object's destructor will be executed when they go out of scope. Whether by a return, by an exception or whatever. If you handle the exception somewhere else, you can be sure all objects from the called function down to your handler will be properly destructed by having their destructor called. They will clean up for you.

Read http://en.wikipedia.org/wiki/Resource_acquisition_is_initialization

Johannes Schaub - litb
+8  A: 

No finally has not been added to C++, nor is it likely to ever be added.

The way C++ uses constructor/destructor makes the need for finally unnecessary.
If you are using catch(...) to cleanup then you are not using C++ properly. The cleanup code should all be in the destructor.

Though it is not a requirement to use it C++ does have a std::exception.
Forcing developers to derive from a specific class to use exception goes against the keep it simple philosophy of C++. Its also why we don't require all classes to derive from Object.

Read: http://stackoverflow.com/questions/161177/does-c-support-finally-blocks-and-whats-this-raii-i-keep-hearing-about/161247#161247

The use of finally is more error prone than destructors to do clean up.
This is because you are forcing the user of the object to do clean up rather than the designer/implementer of the class.

Martin York
the "keep it simple philosophy of C++"? I must have missed that memo
Draemon
+1 Draemon, I was about to say exactly that!
j_random_hacker
It's not a "keep it simple" philosophy, I'd call it more of a "don't set arbitrary restrictions". If C++ won't let you do something, you can bet that there's is a good technical reason behind it (not just a stylistic or best-practices reason).
Eclipse
catch(...) - what good is this construct then? The book examples show doing cleanup actions and re-throwing the exception (as certainly can't get at exception to get info on it and log it).
RogerV
@RogerV: Read me other comments about catching for logging that is not what catch(...) is for. Its about as much use as finally where you don't have access to the current propogating exception either, wich illustrates the power of destructors over finally.
Martin York
+2  A: 

C++ destructors make finally redundant. You can get the same effect by moving the cleanup code from finally to corresponding destructors.

Tanveer Badar
A: 

[At the risk of the down votes, am responding to the above answers here]

If all cleanup always gets done in destructors then there wouldn't need to be any cleanup code in a catch block - yet C++ has catch blocks where cleanup actions get done. Indeed it has a block for catch(...) where it is only possible to do cleanup actions (well, certainly can't get at any exception information to do any logging).

So if cleanup code exist in catch blocks, then there's a reasonable need for a finally block construct as well. The cleanup in a finally block will get done whether there was an exception thrown or not - which is what one always wants to happen when cleanup code does exist.

IOW, the notion that C++ doesn't need a finally block is completely lame. C++ developers from day one have been plagued with having to repeat cleanup actions that appear in catch blocks in the code flow that occurs upon successful exit from the try block. Java and C# programmers just do it once in the finally block.

Having to go off and write C++ class wrappers that have destructors to do cleanup is tedious when life would be a lot simpler to just have a try/finally. If the resource in question is not already wrapped so as to have a destructor, then just let me code try/finally style and be done with it.

When you write application server software like JEE app servers Glassfish, JBoss, etc., you want to be able to catch and log exception information - as opposed to let it fall on the floor. Or worse fall into the runtime and cause a ungraceful abrupt exit of the application server. That's why it's very desirable to have an overarching base class for any possible exception. An exception should be something that it is possible to examine in a context-unaware manner when they're caught. There are many reasons that middle-ware server software became dominated by Java and C# .NET while C++ ceased to have a presence there - this is one of those reasons.

Have done C++ since the CFront days and Java/C# most of this decade. Is clear to see there's just an enormous culture gap in how fundamentally similar things are approached.

RogerV
catch blocks are not only about cleanup. it's about handling the exception in general. think about showing a message box, for example.
Johannes Schaub - litb
also, "Having to go off and write C++ class wrappers that have destructors to do cleanup is tedious when life would be a lot simpler to just have a try/finally." if that is the case,you probably use a C style API. you should lookout for a C++ wrapper for it, or use another API (or write your own) :)
Johannes Schaub - litb
doesn't need a finally block is completely lame: Actually using finally to clean up rather than a destructor is more error prone. Read http://stackoverflow.com/questions/161177/does-c-support-finally-blocks-and-whats-this-raii-i-keep-hearing-about/161247#161247
Martin York
If you need to log things in a Server throw an exception that contains Log information (ie derived from a Log class). Catch the Log exception do the logging re-throw.
Martin York
while C++ ceased to have a presence there: Apache?
Martin York
-1 for being a bit too judgmental about the issue you asked about. (If you've already made up your mind that C++ sucks, why ask the question of how C++ solves the problem?)As most of these answers indicate, the problems you describe only occur if you write "C with classes" code. Learn C++ instead.
jalf
Re: "Having to go off and write C++ class wrappers": a C++ class that doesn't perform its own cleanup in its destructor is *broken*. But if you have to work with a legacy library that breaks this rule, shared_ptr<T> lets you easily specify a cleanup function without having to write any wrappers.
j_random_hacker
try/finally keeps me in scope of the overall logic - think state machine - that my cleanup code can interact with. A destructor wrapper scopes my cleanup code away (it's not a closure after all).
RogerV
Code from 3rd parties may not follow my exception class convention. In Java is the rule to have app servers that execute all manner of third party origininated code. Yet Throwable is the common denominator that enables catching anything and logging it. catch(...) can catch anything but can't log it.
RogerV
@RogerV: You don't need a forced inheritance from a common base class to be able to log it. That is just silly. If you want to log stuff just inherit from a log class. Then catch log-able objects. That seems even more logical that catching everything.
Martin York
@RogerV: Your logic about try/finally is a non sequitur. The use of finally whenever you use a class is just error prone because the user of an object has to make sure the correct clean up is done every time the class is used rather than doing it ONCE in a destructor.
Martin York
Plenty of times I've just needed to consume such a resource one time in my app and move on. You're approach means I need to introduce C++ boiler plate to do so rather than just trivially use an innate feature of the language. Either drag in a library that has the template, or take time to code it.
RogerV
Plus loose access to the outer scope context of where the cleanup code is executing (perhaps want to interact with state machine logic). Destructors seal that cleanup code away scope-wise. See my new addendum comment, though.
RogerV
+12  A: 

My $.02. I've been programming in managed languages like C# and Java for years, but was forced to make the switch to C++ for the purposes of speed. At first I couldn't believe how I had to write out the method signature twice in the header file and then the cpp file, and I didn't like how there was no finally block, and no garbage collection meant tracking memory leaks everywhere - gosh I didn't like it at all!

However, as I said I was forced to use C++. So I was forced to seriously learn it, and now I've finally understood all the programming idioms like RAII and I get all the subtleties of the language and such. It took me a while but now I see just how different of a language it is compared to C# or Java.

These days I think C++ is the best language there is! Yes, I can understand that there is a little more what I call 'chaff' sometimes (seemingly unnecessary stuff to write), but after actually using the language seriously, I've changed my mind about it completely.

I used to have memory leaks all the time. I used to write all my code into the .h file because I hated the separation of code, I couldn't understand why they would do that! And I used to always end up with stupid cyclic include dependencies, and heaps more. I was really hung up on C# or Java, to me C++ was a huge step down. These days I get it. I almost never have memory leaks, I enjoy the separation of interface and implementation, and I don't have problems with cycle dependencies anymore.

And I don't miss the finally block either. To be honest, my opinion is that these C++ programmers that you talk about writing repeated cleanup actions in catch blocks just sound to me like they're just bad C++ programmers. I mean, it doesn't look like any of the other C++ programmers in this thread are having any of the problems you mention. RAII really does make finally redundant, and if anything, it's less work. You write one destructor and then you never have to write another finally ever! Well at least for that type.

With respect, what I think is going on is you're just used to Java now, just like I had been.

Ray Hidayat
+1  A: 

I think that you are missing the point of what catch (...) can do.

You say in your example "alas, can't examine the exception". Well, you have no information about the type of the exception. You don't even know if it's a polymorphic type so even if you had some sort of an untyped reference to it, you couldn't even safely attempt a dynamic_cast.

If you know about certain exceptions or exception hierarchies that you can do something with then this is the place for catch blocks with explicity named types.

catch (...) is not often useful in C++. It can be used in places which have to guarantee that they don't throw, or only throw certain contracted exceptions. If you are using catch (...) for cleanup then there is a very good chance that your code is not robustly exception safe in any case.

As mentioned in other answers, if you are using local objects to manage resources (RAII) then it can be surprising and enlightening how few catch blocks you need, often - if you don't need to do anything locally with an exception - even the try block can be redundant as you let the exceptions flow out to the client code that can respond to them while still guaranteeing no resource issues.

To answer your original question, if you need some piece of code to run at the end of a block, exception or no exception, then a recipe would be.

class LocalFinallyReplacement {
    ~LocalFinallyReplacement() { /* Finally code goes here */ }
};
// ...
{ // some function...
    LocalFinallyReplacement lfr; // must be a named object

    // do something
}

Note how we can completely do away with try, catch and throw.

If you had data in the function that was originally declared outside the try block that you needed access to in the "finally" block, then you may need to add that to the constructor of the helper class and store it until the destructor. However, at this point I would seriously reconsider whether the problem could be resolved by altering the design of the local resource handling objects as it would imply something awry in the design.

Charles Bailey
+8  A: 

Ok, I have to add in an answer to the points you made in a separate answer post: (It would be a lot more convenient if you'd edited this into the original question, so it doesn't end up at the bottom below the answers to it.

If all cleanup always gets done in destructors then there wouldn't need to be any cleanup code in a catch block - yet C++ has catch blocks where cleanup actions get done. Indeed it has a block for catch(...) where it is only possible to do cleanup actions (well, certainly can't get at any exception information to do any logging).

catch has a completely separate purpose, and as a Java programmer you should be aware of that. The finally clause is for "unconditional" cleanup actions. No matter how the block is exited, this must be done. Catch is for conditional cleanup. If this type of exception is thrown, we need to perform a few extra actions.

The cleanup in a finally block will get done whether there was an exception thrown or not - which is what one always wants to happen when cleanup code does exist.

Really? If we want it to always happen for this type (say, we always want to close a database connection when we're done with it), then why don't we define it once? In the type itself? Make the database connection close itself, rather than having to put a try/finally around every single use of it?

That's the point in destructors. They guarantee that each type is able to take care of its own cleanup, every time it's used, without the caller having to think of it.

C++ developers from day one have been plagued with having to repeat cleanup actions that appear in catch blocks in the code flow that occurs upon successful exit from the try block. Java and C# programmers just do it once in the finally block.

No. C++ programmers have never been plagued by that. C programmers have. And C programmers who realized that c++ had classes, and then called themselves C++ programmers have.

I program in C++ and C# daily, and I feel I'm plagued by C#'s ridiculous insistence that I must supply a finally clause (or a using block) EVERY SINGLE TIME I use a database connection or something else that must be cleaned up.

C++ lets me specify once and for all that "whenever we're done with this type, it should perform these actions". I don't risk forgetting to release memory. I don't risk forgetting to close file handles, sockets or database connections. Because my memory, my handles, sockets and db connections do it themselves.

How can it ever be preferable to have to write duplicate cleanup code every time you use a type? If you need to wrap the type because it doesn't have a destructor itself, you have two easy options:

  • Look for a proper C++ library which provides this destructor (hint: Boost)
  • Use boost::shared_ptr to wrap it, and supply it with a custom functor at runtime, specifying the cleanup to be done.

When you write application server software like JEE app servers Glassfish, JBoss, etc., you want to be able to catch and log exception information - as opposed to let it fall on the floor. Or worse fall into the runtime and cause a ungraceful abrupt exit of the application server. That's why it's very desirable to have an overarching base class for any possible exception. And C++ has just such a class. std::exception.

Have done C++ since the CFront days and Java/C# most of this decade. Is clear to see there's just an enormous culture gap in how fundamentally similar things are approached.

No, you've never done C++. You've done CFront, or C with classes. Not C++. There's a huge difference. Quit calling the answers lame, and you might learn something about the language you thought you knew. ;)

jalf
Agreed! Good write up too jalf.
Ray Hidayat
C++ programmers integrating with C libraries - which won't have C++ class destructors. The cleanup action that needs to be done against such a library resource need to get done in either course - some exception being propagated from the try block or when there is a successful exit from the try block
RogerV
Having to go off an wrap resources that don't have destructors smacks of the boilerplate excessiveness that the Ruby folks criticize Java for. I shouldn't have to force my resource into that model (which wasn't designed that way to begin with), when try/finally lets me code its use with robustness.
RogerV
RogerV: Like I said, boost::shared_ptr allows you to specify a custom cleanup function. So even for a C library, you can easily plug the holes by specifying functions to act as destructors.There is nothing robust about try/finally. It is not robust to require the caller to do cleanup every time.
jalf
A: 

I've done plenty of class design and template wrapper design in C++ over those 15 years and done it all the C++ way in terms of destructors cleaning up. Every project, though, also invariably involved the use of C libraries that provided resources with the open it, use it, close it usage model. A try/finally would mean such a resource can just be consumed where it needs to be - in a completely robust manner - and be done with it. The least tedium approach to programming that situation. Could deal with all the other state going on during the logic of that cleanup without having to be scoped away in some wrapper destructor.

I did most of my C++ coding on Windows so could always resort to using Microsoft's __try/__finally for such situations. (Their structured exception handling has some powerful abilities for interacting with exceptions.) Alas, doesn't look like C language has ever ratified any portable exception handling constructs.

That wasn't ideal solution, though, because it was not straightforward to blend C and C++ code in a try block where either style of exception might get thrown. A finally block added to C++ would have been helpful for those situations and would enable portability.

RogerV
C libraries which require manual cleanup are trivially wrapped in RAII classes. This puts all cleanup logic in one place, the dtor of the wrapper. No finally needed here, either. In fact, many C++ OS wrappers like wxWidgets, Qt or even ATL do this with the native C API's to the OS.
MSalters
So rather than write a constructor/destructor once. You prefer to write a try/catch block very time you use it. The seems inherently unsafe in that you write that same block of code again and again. http://stackoverflow.com/questions/498582/smart-pointers-with-a-library-written-in-c/499187#499187
Martin York
Also if you have more than one resource to handle then writing the try/catch/finally correctly is non trivial and thus looks very ugly even in Java.
Martin York
It would be a lot easier to answer your question if you kept the question there... in the question. Right now, we have to read the question, plus two "answer"-questions down at the bottom of the page, and try to figure out some kind of continuity from that. You can edit your question freely instead.
jalf
+3  A: 

To avoid having to define a wrapper class for every releasable resource, you may be interested in ScopeGuard (http://www.ddj.com/cpp/184403758) which allows one to create "cleaners" on the fly.

For example:

FILE* fp = SomeExternalFunction();
// Will automatically call fclose(fp) when going out of scope
ScopeGuard file_guard = MakeGuard(fclose, fp);
Éric Malenfant
Not bad. Vague shades of Ruby's blocks which are code snippets that are like closures, and which are supplied to do a resource cleanup action when the resource is being opened. Aren't there rumblings to add some sort of closure feature to C++ ?
RogerV
+2  A: 

An Example of how difficult it is to use finally correctly.

Open and closing two files.
Where you want to guarantee that the file is closed correctly.
Waiting for the GC is not an option as the files may be re-used.

In C++

void foo()
{
    std::ifstream    data("plop");
    std::ofstream    output("plep");

    // DO STUFF
    // Files closed auto-magically
}

In a language with no destructors but has a finally clause.

void foo()
{
    File            data("plop");
    File            output("plep");

    try
    {
        // DO STUFF
    }
    finally
    {
        // Must guarantee that both files are closed.
        try {data.close();}  catch(Throwable e){/*Ignore*/}
        try {output.close();}catch(Throwable e){/*Ignore*/}
    }
}

This is a simple example and already the code is getting convoluted. Here we are only trying to marshal 2 simple resources. But as the number of resources that need to be managed increases and/or their complexity increases the use of a finally block becomes harder and harder to use correctly in the presence of exceptions.

The use of finally moves responsibility for correct usage onto the user of an object. By using constructor/destructor mechanism provided by C++ you move the responsibility of correct usage to the designer/implementer of the class. This is inheritanly safer as the designer only needs to do it correctly once at the class level (rather than have different users try and do it correctly in different ways).

Martin York
+4  A: 

Cleanup functions, themselves, are thoroughly lame. They have low cohesion, in that they are expected to perform a series of activities only related in when they happen. They have high coupling, in that they need to have their internals modified when the functions that actually do something are changed. Because of this, they're error-prone.

The try...finally construct is a framework for cleanup functions. It is a language-encouraged way to write lousy code. Moreover, since it encourages writing the same cleanup code over and over, it undermines the DRY principle.

The C++ way is far preferable for these purposes. The cleanup code for a resource is written precisely once, in the destructor. It's in the same place as the rest of the code for that resource, and therefore has good cohesiveness. The cleanup code doesn't have to be put into unrelated modules, and therefore this cuts down on coupling. It is written precisely once, when well designed.

Moreover, the C++ way is much more uniform. C++, with the smart pointer additions, handles all sorts of resources in the same way, while Java handles memory well and provides inadequate constructs to release other resources.

There are plenty of problems with C++, but this isn't one of them. There are ways in which Java is better than C++, but this isn't one of them.

Java would be much better off with a way to implement RAII instead of try...finally.

David Thornley
+1  A: 

Not completetely offtopic.

Boiler Plating DB Resource Cleanup in Java

sarcasm mode: Isn't the Java idiom wonderful?

Anonymous
I code JDBC with either Spring-Framework JdbcTemplate or iBATIS. So I don't deal with that manner of boilerplate in practice. Catching exceptions then becomes about repair and retry, roll-back, and/or logging - not cleanup actions (which the framework handles).
RogerV
A: 

Regarding your addendum-edit, yes closures are being considered for C++0x. They can be used with RAII scoped guards to provide an easy to use solution, check Pizer's weblog. They can also be used to mimic try-finally, see this answer ; but is this really a good idea ? .

Luc Hermitte
For one-off situations, sure. If I'm not going to use a resource more than once, then I shouldn't be forced to deal with it using C++ ornate boilerplate idioms. Is what is refreshing about Microsoft's __try/__finally for C. Do the simple thing that is robust, minimal code, and flexible (scope-wise).
RogerV
A: 

Thought I'd add my own solution to this - a kind of smart pointer wrapper for when you have to deal with non-RAII types.

Used like this:

Finaliser< IMAPITable, Releaser > contentsTable;
// now contentsTable can be used as if it were of type IMAPITable*,
// but will be automatically released when it goes out of scope.

So here's the implementation of Finaliser:

/* Finaliser
 Wrap an object and run some action on it when it runs out of scope.
 (A kind of 'finally.')
 * T: type of wrapped object.
 * R: type of a 'releaser' (class providing static void release( T* object )). */
template< class T, class R >
class Finaliser
{
private:
 T* object_;

public:
 explicit Finaliser( T* object = NULL )
 {
  object_ = object;
 }

 ~Finaliser() throw()
 {
  release();
 }

 Finaliser< T, R >& operator=( T* object )
 {
  if (object_ != object && object_ != NULL)
  {
   release();
  }
  object_ = object;

  return *this;
 }

 T* operator->() const
 {
  return object_;
 }

 T** operator&()
 {
  return &object_;
 }

 operator T*()
 {
  return object_;
 }

private:
 void release() throw()
 {
  R::release< T >( object_ );
 }
};

... and here's Releaser:

/* Releaser
 Calls Release() on the object (for use with Finaliser). */
class Releaser
{
public:
 template< class T > static void release( T* object )
 {
  if (object != NULL)
  {
   object->Release();
  }
 }
};

I have a few different kinds of releaser like this, including one for free() and one for CloseHandle().

marijne