C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

try/catch vs. RAII
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
E. Gladyshev
Guest





PostPosted: Thu Jan 15, 2004 10:39 am    Post subject: try/catch vs. RAII Reply with quote




I enjoy articles by Andrei Alexandrescu in CUJ
that are sometimes co-authored by David B. Held.
They are always short and down to the point.

The most recent arcticle CUJ,Feb.2004 is a continuing
discussion on smart_ptr.

I think that the article is missing some clarification
about replacing try/catch with RAII.

I think that at least on Windows, the proposed technique
will work only if the unhandled exception filter
triggers the stack unwinding. However this is not required.

So if you are using a custom unhandled exception filter, be careful!

Andrei's description of this try/catch vs. RAII is that:

--- start of quote (private e-mail) ---
"The following two fragments of code are equivalent:

// 1

try {
statements1
} catch (...) {
statements2
throw;
}
statements2

// 2

struct RAII {
~RAII() {
statements2
}
};

RAII obj;
statements1

Because the two sections of code have identical effect...
--- end of quote ---


In Windows, if the default stack unwinding for *unhandled* exceptions is
disabled, from the exception handling standpoint,
(1) and (2) are obviously not identical.

For example, the following two sections have different effects.

LONG WINAPI er_exception_filter( EXCEPTION_POINTERS *info )
{
exit(0); //don't trigger stack unwinding
}

(1)
main()
{
SetUnhandledExceptionFilter( er_exception_filter );

try {
throw 1;
} catch (...) {
statements2
throw;
}
}
*** statements2 is always called.

(2)

struct RAII {
~RAII() {
statements2
}
};

main()
{
SetUnhandledExceptionFilter( er_exception_filter );

RAII obj;

throw 1;
}
*** statements2 is never called.

In this case you cannot replace try/catch with RAII.

The question is why would someone want to disable
the stack unwinding for unandled exceptions?

For quite sometime, I've been concerned about
frequent catch(...) appearances in CUJ articles.

I finally decided to send an e-mail to Andrei
and David. They were kind enough to follow
up on this issue. Thanks, guys!

I'll be posting another message shortly
about the safety of catch(...) that is
related to the question above.

Eugene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Joshua Lehrer
Guest





PostPosted: Fri Jan 16, 2004 12:53 pm    Post subject: Re: try/catch vs. RAII Reply with quote



"E. Gladyshev" <egladyshev (AT) comcast-nosspam (DOT) net> wrote

Quote:
For quite sometime, I've been concerned about
frequent catch(...) appearances in CUJ articles.


I've been very dissapointed in the overall code quality inside of CUJ
for the past year. The frequently have articles that preach exception
safety and other programming techniques, then, in the same, or a
subsequent issue, they ignore those suggestions.

The way to teach people is not only to show them the right way, but to
practice what you preach so that we see it over and over again.

For example, I was very dissapointed in the code that Shehrzad Qureshi
supplied for his article "Policy-Driven Design & The Intel IPP
Library" in the January, 2004 issue. Here is a snippet:

void resize(int N) {
if (m_pSamples) IPP::free(m_pSamples);
m_nSamples=N;
m_pSamples=IPP::malloc(N);
}

we all know that this is backwards, especially because IPP is a policy
class and may throw any number of exceptions. The author should
practice what is preached in the other articles in the magazine and
write execption safe code. (There are two ways to do it here, one is
to have a very simple custom smart pointer class, thus also removing
the requirement for a destructor bodyl another is to simply call
malloc first, and if that succeeds, store the new sample size then
call free.)

In addition, the code is not const-correct (e.g. "int getNumSamples()
{ return m_nSamples; }"). I could go on about this exact article, but
you get my point.

They have had some nice articles/ideas about locking regions of code:

Lock(mutex) {
}

and yet we still see their code riddled with:

mutex.lock();
operation();
mutex.unlock();

The techniques they have presented are very powerful, but people won't
use them if they are presented and dropped.

There needs to be some minimum standard to which all articles/code
fragments must adhere. I would easily add to this standard
const-correctness and exception safety (unless, of course, either
would overly obfuscate the code and take away from the thrust of the
article, neither of which applies in my above examples.)

joshua lehrer
factset research systems
NYSE:FDS

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David B. Held
Guest





PostPosted: Sat Jan 17, 2004 10:59 am    Post subject: Re: try/catch vs. RAII Reply with quote



"Joshua Lehrer" <usenet_cpp (AT) lehrerfamily (DOT) com> wrote

Quote:
[...]
I've been very dissapointed in the overall code quality inside of CUJ
for the past year. The frequently have articles that preach exception
safety and other programming techniques, then, in the same, or a
subsequent issue, they ignore those suggestions.
[...]

Unfortunately, CUJ isn't a peer-reviewed journal, so unless you're
volunteering to review articles...

Dave



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system ([url]http://www.grisoft.com)[/url].
Version: 6.0.561 / Virus Database: 353 - Release Date: 1/13/2004



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Anderson
Guest





PostPosted: Mon Jan 19, 2004 12:27 am    Post subject: Re: try/catch vs. RAII Reply with quote


----- Original Message -----
From: "E. Gladyshev" <egladyshev (AT) comcast-nosspam (DOT) net>
Newsgroups: comp.lang.c++.moderated
Sent: Thursday, January 15, 2004 5:39 AM
Subject: try/catch vs. RAII


Quote:

blabla...

The most recent arcticle CUJ,Feb.2004 is a continuing
discussion on smart_ptr.

I think that the article is missing some clarification
about replacing try/catch with RAII.

I think that at least on Windows, the proposed technique
will work only if the unhandled exception filter
triggers the stack unwinding. However this is not required.

Well if the exception handler does not trigger stack unwinding,
you are out of C++ realms, so CUJ does not have to cover that

Quote:

So if you are using a custom unhandled exception filter, be careful!

Well if someone use a custom unhandled exception filter, I hope he is
knowledgeable
about how to do it.
Quote:

Andrei's description of this try/catch vs. RAII is that:

more stuff


In Windows, if the default stack unwinding for *unhandled* exceptions is
disabled, from the exception handling standpoint,
(1) and (2) are obviously not identical.

But then you are not in Kansas anymore !
Quote:

For example, the following two sections have different effects.

LONG WINAPI er_exception_filter( EXCEPTION_POINTERS *info )
{
exit(0); //don't trigger stack unwinding

then thowing an exception is equivalent to "exit"
so in your code you could replace all your throw by exit, it would be
equivalent.

Quote:
}

(1)
main()
{
SetUnhandledExceptionFilter( er_exception_filter );

try {
throw 1;
} catch (...) {
statements2
throw;
}
}
*** statements2 is always called.

Are you sure ???
without verifying, it seems that the filter will exit.
unless the catch at the same level prevent the filter from being called.
still you are deep in implementation defined land

Quote:

(2)

struct RAII {
~RAII() {
statements2
}
};

main()
{
SetUnhandledExceptionFilter( er_exception_filter );

RAII obj;

throw 1;
}
*** statements2 is never called.

What a surprise!!! (mild sarcasm)
Quote:

In this case you cannot replace try/catch with RAII.

The question is why would someone want to disable
the stack unwinding for unandled exceptions?

Yeah, why ?

especially if the change breaks valid code.
The best exception filter I've seen was from boost:

LONG WINAPI er_exception_filter( EXCEPTION_POINTERS *info )
{
throw; // operate like real C++ now
}

Quote:

more stuff deleted...

I'll be posting another message shortly
about the safety of catch(...) that is
related to the question above.

keep us inform, please.


exception handling is still misterious for many programmers, and
implementation
seems to differ greatly across compiler.

A good thread about exception dos and dont's would be great.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
E. Gladyshev
Guest





PostPosted: Tue Jan 20, 2004 11:24 am    Post subject: Re: try/catch vs. RAII Reply with quote


"Daniel Anderson" <danderson007 (AT) sympatico (DOT) ca> wrote

[...]
Quote:
Well if the exception handler does not trigger stack unwinding,
you are out of C++ realms, so CUJ does not have to cover that


15.5.1/2
Note: in the situation where
no matching handler is found, it is implementation-defined whether or
not the stack is unwound before terminate() is called. In all other
situations, the stack shall not be unwound before terminate() is
called.


I think that it is very important to realize that replacing
try/catch() with RAII is not a portable idiom.

Eugene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David B. Held
Guest





PostPosted: Wed Jan 21, 2004 9:05 am    Post subject: Re: try/catch vs. RAII Reply with quote

"E. Gladyshev" <egladyshev (AT) comcast-nosspam (DOT) net> wrote

Quote:
[...]
I think that it is very important to realize that replacing
try/catch() with RAII is not a portable idiom.

It's completely portable w.r.t. C++. What is not portable is the
implementation-specific behavior of unhandled exceptions on
which you depend.

Dave



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system ([url]http://www.grisoft.com)[/url].
Version: 6.0.561 / Virus Database: 353 - Release Date: 1/13/2004



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
smitty_one_each
Guest





PostPosted: Wed Jan 21, 2004 7:52 pm    Post subject: Re: try/catch vs. RAII Reply with quote

Quote:
Unfortunately, CUJ isn't a peer-reviewed journal, so unless you're
volunteering to review articles...

Dave

Furthermore, decorating the code with all of the received wisdom of
the community is likely to obscure whatever point an article is trying
to make.
Maybe a reasonable medium is that authors make their point briefly
print, and then post fully-rendered examples on www.cuj.com, where
peer-review can occur.
Dangerous novices like me benefit greatly from the gurus. ;)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Teh (tî'pô)
Guest





PostPosted: Thu Jan 22, 2004 2:45 pm    Post subject: Re: try/catch vs. RAII Reply with quote

Joshua Lehrer proclaimed:
Quote:
They have had some nice articles/ideas about locking regions of code:

Lock(mutex) {
}

Could you elaborate on this? I don't see how this can be done, well
not without a MACRO anyway.

Here's what I came up with (scoped_lock does what you'd expect).

class Locker {
scoped_lock lock;
public:
Locker(mutex m) : lock(m) { }
operator bool() const { return true; }
}

// For some reason CC doesn't like Locker lock(M) it wants
// an assignment although they're equivalent (AFAIK)
#define Lock(M)
if(Locker locker_obj_I_hope_this_name_is_not_used_in_the_block = M)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Jan 23, 2004 9:51 am    Post subject: Re: try/catch vs. RAII Reply with quote

[email]usenet_cpp (AT) lehrerfamily (DOT) com[/email] (Joshua Lehrer) wrote in message
news:<31c49f0d.0401151010.6a79927b (AT) posting (DOT) google.com>...
Quote:
"E. Gladyshev" <egladyshev (AT) comcast-nosspam (DOT) net> wrote in message
news:<HdoNb.69615$xy6.129377@attbi_s02>...

For quite sometime, I've been concerned about
frequent catch(...) appearances in CUJ articles.

I've been very dissapointed in the overall code quality inside of CUJ
for the past year.

I find that the quality is very variable, and there is, from time to
time, an article which is really bad. On the other hand, the quality of
code from their regular contributors is exceptional.

[...]
Quote:
They have had some nice articles/ideas about locking regions of code:

Lock(mutex) {
}

and yet we still see their code riddled with:

mutex.lock();
operation();
mutex.unlock();

IMHO, you've hit here on a delicate point. If the article isn't
concerned with threading, then why bother with mutex at all. And if it
is... often, the exact moment locking and unlocking occurs is likely to
be of the utmost importance, and using specific operations to show this
moment is good pedogogy, even if it isn't the way to go in production
code.

Quote:
The techniques they have presented are very powerful, but people won't
use them if they are presented and dropped.

There needs to be some minimum standard to which all articles/code
fragments must adhere. I would easily add to this standard
const-correctness and exception safety (unless, of course, either
would overly obfuscate the code and take away from the thrust of the
article, neither of which applies in my above examples.)

I agree that a minimum standard is needed. I certainly think that const
correctness must be part of it. The exception safety issue is somewhat
more delicate, however, since exception safety is much more a question
of contract (strong guarantee, etc.) than anything else. Blatently wrong
code (e.g. where an exception is a definite possiblity, and it would
result in a double delete) should be rejected, but it is not always easy
to recognize.

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Jan 23, 2004 9:54 am    Post subject: Re: try/catch vs. RAII Reply with quote

"E. Gladyshev" <egladyshev (AT) comcast-nosspam (DOT) net> wrote

Quote:
"Daniel Anderson" <danderson007 (AT) sympatico (DOT) ca> wrote in message
news:41BOb.228
[...]
Well if the exception handler does not trigger stack unwinding,
you are out of C++ realms, so CUJ does not have to cover that

15.5.1/2
Note: in the situation where
no matching handler is found, it is implementation-defined whether or
not the stack is unwound before terminate() is called. In all other
situations, the stack shall not be unwound before terminate() is
called.

I think that it is very important to realize that replacing
try/catch() with RAII is not a portable idiom.

I think that there is a basic premise when using exceptions that all
exceptions will be caught. Somewhere. I don't think I've written a
single program for a modern compiler in which main didn't consist of a
single try/catch block.

Note that neither RAII nor try/catch can totally ensure that all
resources (including such things as temporary files) are freed. There
are any number of things which can cause the program to terminate
without stack walkback: on my systme: abort or an assertion failure, a
segment violation, a kill -9 on the process... Abort and assertion
failure are generally portable, and on must systems, dereferencing a
null pointer is another good way. Pulling the plug on the computer will
often do the trick as well.

I think that when talking about C++ techniques, there is a general
assumption that the surrounding environment (both inside and outside the
program) is reasonably well behaved. I would consider that this is NOT
the case for a program which allowed an uncaught exception to terminate
the program.

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Kamil Burzynski
Guest





PostPosted: Fri Jan 23, 2004 10:13 am    Post subject: Re: try/catch vs. RAII Reply with quote

On 22 Jan 2004 09:45:45 -0500, Teh (tî'pô) wrote:
Quote:
Joshua Lehrer proclaimed:

class Locker {
scoped_lock lock;
public:
Locker(mutex m) : lock(m) { }
operator bool() const { return true; }
}

// For some reason CC doesn't like Locker lock(M) it wants
// an assignment although they're equivalent (AFAIK)
#define Lock(M)
if(Locker locker_obj_I_hope_this_name_is_not_used_in_the_block = M)

Maybe because of lack of reference in constructor? Ie. something like
this:
Locker( mutex &m ) : lock( m ) { };

could be better? I'm not sure which mutexes are you using, however :)

Myself I've written simple Sentry classes:

class MutexSentry
{
private:
Mutex &m;

public:
MutexSentry( Mutex &m )
{
m.Lock();
}
~MutexSentry()
{
m.UnLock();
}
};

works nice for that:

void foo()
{
//...
{
MutexSentry m( mutex );

//...
}
//...
}

Btw. I've found that ocassionally MutexUnSentry is also convenient.
UnSentry is similar to Sentry, but it have Lock() and UnLock() reversed.

--
Best regards from
Kamil Burzynski

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Fri Jan 23, 2004 10:22 am    Post subject: Re: try/catch vs. RAII Reply with quote

Teh (tî'pô) wrote:
Quote:
Joshua Lehrer proclaimed:
They have had some nice articles/ideas about locking regions of code:

Lock(mutex) {
}

Could you elaborate on this? I don't see how this can be done, well
not without a MACRO anyway.

Here's what I came up with (scoped_lock does what you'd expect).

class Locker {
scoped_lock lock;
public:
Locker(mutex m) : lock(m) { }
operator bool() const { return true; }
}

// For some reason CC doesn't like Locker lock(M) it wants
// an assignment although they're equivalent (AFAIK)
#define Lock(M)
if(Locker locker_obj_I_hope_this_name_is_not_used_in_the_block = M)

They're not equivalent:
Locker lock = M;
is basically equivalent to
Locker lock(Locker(M));
and is not valid because Locker is not copyable.

Your original
Locker lock(M);
"ought to" work but it isn't an acceptable form of declaration in a
conditional or loop statement.

This appears to work, though it's not great:

class Locker
{
public:
Locker(mutex & m) : l_(m), m_(m) {}
Locker(const Locker & l)
: l_(l.m_, false), m_(l.m_)
{
l.l_.unlock();
l_.lock();
}
operator const void *() const { return this; }
private:
mutable scoped_lock l_;
mutex & m_;
};

#define Lock(m) if (Locker Lock = (m))

Hopefully the compiler eliminates the copy, since it is very
inefficient to lock, unlock and then lock again! However this
should work correctly whether or not the copy is done.

Note use of "Lock" as the variable name - this should be safe
since "Lock" is otherwise reserved as the name of the macro.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Richter
Guest





PostPosted: Fri Jan 23, 2004 8:49 pm    Post subject: Re: try/catch vs. RAII Reply with quote

Hi,

Quote:
They have had some nice articles/ideas about locking regions of code:

Lock(mutex) {
}

Could you elaborate on this? I don't see how this can be done, well
not without a MACRO anyway.

Not exactly with the syntax above, but the idea is to have a class
that is constructed from the mutex where the mutex is locked in the
constructor and released in the destructor. This way the mutex is
even exception safe. In a second step, derive classes you want to
synchronize on from a base class that just carries the mutex. This
way you can mimic the Java/C# 'synchronized' regions.

class Lock {
//
Mutex &holder;
..
//
public:
Lock(Mutex &mutex)
: holder(mutex)
{
mutex.lock();
}
~Lock()
{
holder.unlock();
}
};


Then:
{
Lock l(mutex);
...
}

synchronizes the region on the mutex.

Greetings,
Thomas


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Mang
Guest





PostPosted: Fri Jan 23, 2004 9:13 pm    Post subject: Re: try/catch vs. RAII Reply with quote



Ben Hutchings schrieb:

Quote:

They're not equivalent:
Locker lock = M;
is basically equivalent to
Locker lock(Locker(M));

No, they are definitely not equivalent.

The first constructs a lock, while the second declares a function.

regards,

Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
E. Gladyshev
Guest





PostPosted: Sat Jan 24, 2004 9:37 pm    Post subject: Re: try/catch vs. RAII Reply with quote


<kanze (AT) gabi-soft (DOT) fr> wrote

[...]
Quote:
I think that it is very important to realize that replacing
try/catch() with RAII is not a portable idiom.

I think that there is a basic premise when using exceptions that all
exceptions will be caught.

No, the standard doesn't require that.
What premise are you talking about?

Quote:
Somewhere. I don't think I've written a
single program for a modern compiler in which main didn't consist of a
single try/catch block.

I guess I would like to repeat this again.
Unfortunately try/catch block in main() is not always enough.
If you program or any of the third party libraries create
threads, you have to put try/catch in each of these threads.
Unfortunately it is not always possible.

Eugene


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.