Finally in CPP

Started by
20 comments, last by jpetrie 17 years, 6 months ago
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.
It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Advertisement
Read. And next time Google first.
So the solution is to put the pointer in a class and in the dtr set it to NULL?
That doesnt make any sense.
I don't understand how it should be implemented.
It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
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.)
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.
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.
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 :)

[size=2]aliak.net
If destructors are throwing exceptions, then you have bigger problems to worry about.
daerid@gmail.com
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.

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

This topic is closed to new replies.

Advertisement