473,395 Members | 1,885 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

try/finally implementation in c++

Hi all

Its one of my little pragramming challenges to implement a try/finally
construct in C++. I have done several implementations but they all have
limitations. Have tried mostly using a destructor to execute the
"finally" code. However this has the big limitation that the destructor
cannot see local variables. Another approach that solves this problem
is the following:

{
MyBaseException* handledException = NULL;
try
{
<try code>
}
catch(MyBaseException& e)
{
handledException = e.Clone();
}

<finally code>

if (handledException)
throw *handledException;
}

However, this method has the limitation that it works only for specific
classes of exception objects.

I'm curious to see other ideas

Regards
Alex

Mar 31 '06 #1
10 11985

avasilev wrote:
Hi all

Its one of my little pragramming challenges to implement a try/finally
construct in C++. I have done several implementations but they all have
limitations. Have tried mostly using a destructor to execute the
"finally" code. However this has the big limitation that the destructor
cannot see local variables.


Not that I am recommending it but...

It could if the destructor was part of a local struct containing those
variables.

Something to think about.

Mar 31 '06 #2
avasilev wrote:
I'm curious to see other ideas


news:comp.lang.c++.moderated has a humongous multi-thread conversation on
this topic. Someone has suggested adding a 'finally' keyword to the
language.

I find the idea that anyone thinks C++ can learn something about cleanup
from Java very disturbing.

Most sources recommend RAII for C++'s exception-neutral cleanup mechanism.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 31 '06 #3
* avasilev wrote, on 31/03/2006 22:58:

I'm curious to see other ideas


Disregard the natural language text (if you don't know Norwegian) and
concentrate on links & code:

<url: http://utvikling.com/cppfaq/04/04/02/index.html>.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Mar 31 '06 #4

"Phlip" <ph*******@gmail.com> wrote in message
news:KT****************@newssvr24.news.prodigy.net ...
avasilev wrote:
I'm curious to see other ideas
news:comp.lang.c++.moderated has a humongous multi-thread conversation on
this topic. Someone has suggested adding a 'finally' keyword to the
language.

I find the idea that anyone thinks C++ can learn something about cleanup
from Java very disturbing.


Could be a Pascal programmer... using try..finally was a standard way to do
things in Delphi.

But I think it's _always_ possible to learn from other languages. (Of
course, sometimes you just learn what's NOT so good, though...) :-)
Most sources recommend RAII for C++'s exception-neutral cleanup mechanism.


Yep. (But it's a bit of a pain sometimes to make a new class just to handle
what would only be a couple extra lines of code (i.e., the try/finally
keywords), if C++ _were_ to implement it.) Still, I'd agree that RAII is
probably the best solution, at least currently.

-Howard
Mar 31 '06 #5
Yes, this is something I have thought about. The problem is that it is
quite slow. Imagine that this code executes in a loop - every time it
will throw two exceptions, depending on the compiler/runtime this could
execute terribly slow.

Mar 31 '06 #6
avasilev wrote:
{
MyBaseException* handledException = NULL;
try
{
<try code>
}
catch(MyBaseException& e)
{
handledException = e.Clone();
}

<finally code>

if (handledException)
throw *handledException;
}

However, this method has the limitation that it works only for specific
classes of exception objects.


It also has the limitation of leaking memory from every try/catch block
whenever it catches an exception, unless you've got some mechanism for
telling a catch handler to delete the exception.

Bob

Mar 31 '06 #7
It's true, I have programmed in Delphi a lot, but I am not trying to
make C++ behave like Delphi. One of the reasons for which I like C++ is
that it gives a lot more freedom. However, I think particularly this
issue does the opposite - limits your freedom - RAII is not universal.
Sometimes it is hard/ugly to encapsulate everything that has to be
cleaned up in one class, so that the destructor can access it. For
example - when some of the resources are already encapsulated more
appropriately in other classes. Then the solution would be either to
redesign the whole class structure artificially so that RAII can be
applied, thus screwing up the design for the sake of RAII. The other
approach could be to pass references to external resources to the
object so that the constructor/destructor can acces it. So I think
forcing the use of RAII and claiming that it is the ultimate solution
in all cases is not in the C++ spirit.

Mar 31 '06 #8
avasilev wrote:
So I think
forcing the use of RAII and claiming that it is the ultimate solution
in all cases is not in the C++ spirit.
I'm not sure who you reply to, but I didn't claim RAII is ultimate. I think
block closures are, but we won't see those in C++ for a while.

Consider this C++ -like code:

Foo()
{
Bar aBar;
aBar.dirty();
finally:
aBar.clean();
}

Implement 'finally' as you like - as a keyword, or a catch().

The problem with that code is it couples Bar's private internal state to
Foo. If you change how dirty Bar gets, you must find every client of Bar
and upgrade the finally block. Bar's cleaness should be a private,
encapsulated detail.
Sometimes it is hard/ugly to encapsulate everything that has to be
cleaned up in one class, so that the destructor can access it.


And sometimes that is a sign that the client function (Foo()) is doing too
much, and it needs its statements refactored into Bar classes, to
encapsulate everything about them, not just how they clean up.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 31 '06 #9
Philip, sorry for the misunderstanding. What i meant was that the
language forces you to use RAII, and indirectly (or maybe directly, I
remember reading answers to language extension proposals) the C++
standards committee thus claims it is _the_ way to do things.
I agree that the code you give as an example has this problem. In this
case RAII is more appropriate. There is the problem for exposing
internal state, but if the onterface of the resource is designed and
implemented correctly, then this should not be an issue.
Often there is not just one line of code that has to be executed in
finally, and not referring to only one resourece. There could be many
finally blocks in different parts of the application, referring to same
resources. The semantics of the blocks could no be just "cleanup",
could be more complicated - e.g. signalling events etc. Probably it
could always be implemented with RAII, but this can be a pain and can
complicate things.

Alex

Mar 31 '06 #10
avasilev wrote:
Hi all

Its one of my little pragramming challenges to implement a try/finally
construct in C++. I have done several implementations but they all have
limitations.
An unwind protect mechanism is architectural. If it's not in the
substrate, it may be impossible to implement 100%. There are semantic
pieces in C++ that could do the job, but the syntactic abstraction
isn't there.
I'm curious to see other ideas


Firstly, separate the finally mechanism from try and catch. Conflating
them together is an unnecessary Java thing which you don't have to
adopt. In some other languages, the mechanism that means "execute this
regardless of how this terminates" is a separate construct. Common Lisp
calls it unwind-protect, a term that is sometimes used outside of Lisp
to refer to any such a mechanism..

If you separate it out, you have a simpler job, because your syntax
does not have to incorporate catch blocks for exceptions. It has only
two pieces: the block that is protected, and the code that is run
unconditionally.

The problem is that you need the unconditional code in two places:
immediately following the protected code (normal return case) and in a
catch (...) handler.

To do this, you can make the entire code into a giant macro argument,
by doing which you end up with something that combines ugly appearance
with debugger hostility:

#include <iostream>

#define ugly_unwind_protect(block, cleanup) \
try { block } catch (...) { cleanup throw; } cleanup

int main()
{
int x = 3;

try {
ugly_unwind_protect (
{
throw 42;
},
{
// demonstrate access to locals
std::cout << "x = " << x << std::endl;
}
)
} catch (int ex) {
// the 42 is caught here
std::cout << "ex = " << ex << std::endl;
}

return 0;
}

Oh yeah, because statements are passed as a single macro argument,
commas in them can cause problems. Try changing it to "throw 0, 42" and
see, hahaha. That's only a problem for commas that are not enclosed in
parentheses.

As you can see, you can get all the functionality of try/catch/finally
with try/catch and a separate unwind-protect.

Note how the unwind code is duplicated textually in two places. Yuck!

Apr 1 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Brian Kelley | last post by:
def res(): try: a = 1 return finally: print "do I get here?" res() outputs "do I get here?"
6
by: Colin Brown | last post by:
When I run this code and then immediately do a Control-C, I do not get the 'thread' printed? Colin Brown PyNZ ----------------------------------------------------------- import thread, time ...
9
by: David Stockwell | last post by:
In referring to my copy of the python bible, it tells me I can't use all three items 'try' except and finally. I can use the t/f or t/e combinations though What combination can i use if i want...
77
by: Jon Skeet [C# MVP] | last post by:
Please excuse the cross-post - I'm pretty sure I've had interest in the article on all the groups this is posted to. I've finally managed to finish my article on multi-threading - at least for...
21
by: Mark Broadbent | last post by:
Consider the following statements //------- Item i = Basket.Items; //indexer is used to return instance of class Item Basket.Items.Remove(); //method on class item is fired item i = new...
1
by: VB Programmer | last post by:
I usually put my declarations for db connections, datasets, datareaders, etc... above the Try portion. Inside the Try is where I open my connection, executereader, etc... In the Catch portion I...
23
by: VB Programmer | last post by:
Variable scope doesn't make sense to me when it comes to Try Catch Finally. Example: In order to close/dispose a db connection you have to dim the connection outside of the Try Catch Finally...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.