Jump to content
  • Advertisement
Sign in to follow this  
The C modest god

Finally in CPP

This topic is 4281 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was told there is somethin called finally in CPP that can be implemented with the try mechanisem. What I want to do is that a given scope (i.e. {}) of code, will be completly executed even if there is an exception in the middle of it. In case an exception occured while in this block, the program will finish doing the whole block and then it will trhow the exception onward. A simple example would be:
delete this->ptr;
this->ptr = NULL;
The problem with this code is that if an exception occur in the middle of delete this->ptr; it wont reach the line which sets this->ptr to NULL. This is the sort of problem I want to solve. I can simply do the following:
T * ptrKeep;
ptrKeep = this->ptr;
this->ptr = NULL;
delete ptrKeep;
But I want to do it with the try{} mechanisem. Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
In the special case of a pointer, you can use auto_ptr. (Which, BTW, it tells you right on that same page right below the question about finally.)

Share this post


Link to post
Share on other sites
Quote:
The problem with this code is that if an exception occur in the middle of delete this->ptr; it wont reach the line which sets this->ptr to NULL.

...

The only time that should raise an exception (AFAIK) is when the this pointer is invalid. In which case your object doesn't exist or is otherwise fuxxored, and you've probably got more problems than a pointer not being set to NULL.

Share this post


Link to post
Share on other sites
You will also want to look into the RAII idiom. It is essential for implementing exception-safe code in a sane, manageable fashion (which is what you seem to really want to know). Google can help you out there, as well. std::auto_ptr and boost::shared_ptr are very helpful for this as well.

Also, your example is flawed. A destructor should never throw an exception. Read this for more information.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mushu
Quote:
The problem with this code is that if an exception occur in the middle of delete this->ptr; it wont reach the line which sets this->ptr to NULL.

...

The only time that should raise an exception (AFAIK) is when the this pointer is invalid. In which case your object doesn't exist or is otherwise fuxxored, and you've probably got more problems than a pointer not being set to NULL.


or if the destructor of whatever ptr is throws an exception, in which case he's still got more problems then an object not being set to NULL :)

Share this post


Link to post
Share on other sites
Lets just repeat that for emphasis : Write all destructors as if they have an exception specification of throw(). Furthermore, assume all destructors behave as if they have an exception specification of throw(). A destructor that throws is always exception un-safe. You gain nothing from attempting to correct that behavior in client code.

However, delete CAN throw. In the case where delete throws, the destructor has already been called. Now, delete should only throw when you have corrupted the heap somehow, or aren't deleting a deletable object. All these cases are usually caught by the operating system as an access violation or seg fault, and represent a much more sinister bug.

When delete is called in a destructor, and that destructor is called as a result of stack unwinding while propogating an exception, and that call to delete throws an exception, there is nothing you can do anyway. When delete exits by throwing, while stack unwinding is already occuring, the result is a call to terminate.

In general, when you error while releasing a resource, theres not much you can do. Should you try and release it again? Probably not. It will just fail again. Usually, the best you can do is forget about it.

But there is certainly a benefit when the resource in question is something such as a socket or file handle. Failing to close a file handle is an error; but you should still try and clean up any other handles you have open.

Incidentally, the solution to your problem is just to not propogate the exception. If you fail to release the memory, theres nothing more you can do about that exception, so just forget it. Your code becomes


try
{
delete pointer;
} catch (...) {}
pointer = 0;


If delete throws, the memory is leaked. But it was going to leak anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by Deyja
However, delete CAN throw. In the case where delete throws, the destructor has already been called. Now, delete should only throw when you have corrupted the heap somehow, or aren't deleting a deletable object. All these cases are usually caught by the operating system as an access violation or seg fault, and represent a much more sinister bug.


Just to clarify, delete cannot throw a C++ exception. It may throw an exception of the underlying hardware/operating system (a Windows Structured Exception under Windows), but there is no guarantee that this exception can be caught by the C++ exception mechanism (under Windows only C++ exception mechanisms which are built on top of the Windows Structured Exception mechanism can catch Windows Structured Exceptions. I believe only Visual C++ is implemented this way due to legal reasons).

Σnigma

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!