Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Exception propagation

Reply
Thread Tools

Exception propagation

 
 
ittium
Guest
Posts: n/a
 
      12-10-2011
Group,

I have a situation where some of the class/non-class methodsmake many
levels of function calls, some of the function in this call hierarchy
may throw exception, what is a good idea

#1 inner function rethrow (by empty throw), such that exception is
propagated back to the top level function.

#2inner function does not throw (by empty throw), this exception will be
by **default** propagated back to the top level routine (assuming
intermediate routines are not catching the exception).

#3 When it is a good idea that function(inner) receiving the exception
or some intermediate function catch it and from there error event is
propagated back through some error code.

thanks
Ittium
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      12-10-2011
On 12/10/11 09:28 PM, ittium wrote:
> Group,
>
> I have a situation where some of the class/non-class methodsmake many
> levels of function calls, some of the function in this call hierarchy
> may throw exception, what is a good idea
>
> #1 inner function rethrow (by empty throw), such that exception is
> propagated back to the top level function.
>
> #2inner function does not throw (by empty throw), this exception will be
> by **default** propagated back to the top level routine (assuming
> intermediate routines are not catching the exception).
>
> #3 When it is a good idea that function(inner) receiving the exception
> or some intermediate function catch it and from there error event is
> propagated back through some error code.



The first place where it makes sense to catch the exception catches it
and performs the appropriate recovery actions. if there isn't an
appropriate place, catch it in main, report and exit.

--
Ian Collins
 
Reply With Quote
 
 
 
 
Goran
Guest
Posts: n/a
 
      12-10-2011
On Dec 10, 9:28*am, ittium <(E-Mail Removed)> wrote:
> Group,
>
> I have a situation where some of the *class/non-class methodsmake many
> levels of function calls, some of the function in this call hierarchy
> may throw exception, what is a good idea
>
> #1 inner function rethrow (by empty throw), such that exception is
> propagated back to the top level function.
>
> #2inner function does not throw (by empty throw), this exception will be
> by **default** propagated back to the top level routine (assuming
> intermediate routines are not catching the exception).
>
> #3 When it is a good idea that function(inner) receiving the exception
> or some intermediate function catch it and from there error event is
> propagated back through some error code.


In C++ code, there's no good reason to ever STOP exception propagation
AND replace it with return code, except e.g. in main. Or perhaps when
you are writing a module that should be exposed to a language that
can't receive C++ exceptions.

Further, there are RARE reasons to stop exception propagation. Off the
top of my head, some of those rare ones are:

* main() - you seldom want want terminate() to kick in, which is what
will happen if exception escapes main()
* for similar reason, any top-level thread function
* to re-throw existing exception, but with further info about the
error (e.g. "bad_alloc happened when fryding the swoorf"). This is
because lowest-level exceptions have no further info about the context
in which they happened, and that is useful, and C++ has no call stack
in exception objects .
* there's a loop whose whole body can fail, but next iteration still
should happen, usually after reporting the error. Example: a server-
kind-of-a-program, who has a client serving loop, and serving one
client request failed.

You seem to be trying to make a rule of thumb here, but without the
context. That is seldom a good idea. It's better to ask "what should I
do" from a given context.

Goran.
 
Reply With Quote
 
Christopher
Guest
Posts: n/a
 
      12-11-2011
On Dec 10, 12:29*pm, Goran <(E-Mail Removed)> wrote:
> On Dec 10, 9:28*am, ittium <(E-Mail Removed)> wrote:
>
>
>
>
>
> > Group,

>
> > I have a situation where some of the *class/non-class methodsmake many
> > levels of function calls, some of the function in this call hierarchy
> > may throw exception, what is a good idea

>
> > #1 inner function rethrow (by empty throw), such that exception is
> > propagated back to the top level function.

>
> > #2inner function does not throw (by empty throw), this exception will be
> > by **default** propagated back to the top level routine (assuming
> > intermediate routines are not catching the exception).

>
> > #3 When it is a good idea that function(inner) receiving the exception
> > or some intermediate function catch it and from there error event is
> > propagated back through some error code.

>
> In C++ code, there's no good reason to ever STOP exception propagation
> AND replace it with return code, except e.g. in main. Or perhaps when
> you are writing a module that should be exposed to a language that
> can't receive C++ exceptions.
>
> Further, there are RARE reasons to stop exception propagation. Off the
> top of my head, some of those rare ones are:
>
> * main() - you seldom want want terminate() to kick in, which is what
> will happen if exception escapes main()
> * for similar reason, any top-level thread function
> * to re-throw existing exception, but with further info about the
> error (e.g. "bad_alloc happened when fryding the swoorf"). This is
> because lowest-level exceptions have no further info about the context
> in which they happened, and that is useful, and C++ has no call stack
> in exception objects .
> * there's a loop whose whole body can fail, but next iteration still
> should happen, usually after reporting the error. Example: a server-
> kind-of-a-program, who has a client serving loop, and serving one
> client request failed.
>
> You seem to be trying to make a rule of thumb here, but without the
> context. That is seldom a good idea. It's better to ask "what should I
> do" from a given context.
>
> Goran.- Hide quoted text -
>
> - Show quoted text -



Catching an exception at the top level function of a thread is not so
rare in my opinion and very often overlooked.
I've actually made it a point to examine thread entry points now, and
make sure everything is caught and handled in some way.

 
Reply With Quote
 
Ebenezer
Guest
Posts: n/a
 
      12-12-2011
On Dec 10, 12:29*pm, Goran <(E-Mail Removed)> wrote:
>
> In C++ code, there's no good reason to ever STOP exception propagation
> AND replace it with return code, except e.g. in main. Or perhaps when
> you are writing a module that should be exposed to a language that
> can't receive C++ exceptions.
>
> Further, there are RARE reasons to stop exception propagation. Off the
> top of my head, some of those rare ones are:
>
> * main() - you seldom want want terminate() to kick in, which is what
> will happen if exception escapes main()
> * for similar reason, any top-level thread function
> * to re-throw existing exception, but with further info about the
> error (e.g. "bad_alloc happened when fryding the swoorf"). This is
> because lowest-level exceptions have no further info about the context
> in which they happened, and that is useful, and C++ has no call stack
> in exception objects .
> * there's a loop whose whole body can fail, but next iteration still
> should happen, usually after reporting the error. Example: a server-
> kind-of-a-program, who has a client serving loop, and serving one
> client request failed.
>


Well that last one is hardly rare. Most programs today are
servers, I think.


I stop the propagation in the following for performance
reasons:

cmw_request
getRequest (uint8_t byteOrder
, sock_type sock)
{
static ReceiveBuffer<SameFormat> localbuf(4096);
#ifdef ENDIAN_BIG
static ReceiveBuffer<LeastSignificantFirst> otherlocalbuf(4096);
#else
static ReceiveBuffer<MostSignificantFirst> otherlocalbuf(4096);
#endif

uint8_t clientFormat;
Read(sock, &clientFormat, 1);
try {
if (clientFormat == byteOrder) {
localbuf.sock_ = sock;
while (!localbuf.GotPacket()) ;
return cmw_request(localbuf);
} else {
otherlocalbuf.sock_ = sock;
while (!otherlocalbuf.GotPacket()) ;
return cmw_request(otherlocalbuf);
}
} catch (::std::exception const& ex) {
clientFormat == byteOrder ? localbuf.Reset() :
otherlocalbuf.Reset();
throw;
}
}

The exception catching allows me to make some variables
static that would otherwise be allocating and releasing
memory from the heap each time the function is called.
It is kind of experimental, but so far so good.

The above function is from this file --
http://webEbenezer.net/misc/cmwAmbassador.cc.


Brian Wood
Ebenezer Enterprises
http://webEbenezer.net
 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      12-12-2011
On Dec 12, 6:44*am, Ebenezer <(E-Mail Removed)> wrote:
> On Dec 10, 12:29*pm, Goran <(E-Mail Removed)> wrote:
>
>
>
>
>
>
>
>
>
>
>
> > In C++ code, there's no good reason to ever STOP exception propagation
> > AND replace it with return code, except e.g. in main. Or perhaps when
> > you are writing a module that should be exposed to a language that
> > can't receive C++ exceptions.

>
> > Further, there are RARE reasons to stop exception propagation. Off the
> > top of my head, some of those rare ones are:

>
> > * main() - you seldom want want terminate() to kick in, which is what
> > will happen if exception escapes main()
> > * for similar reason, any top-level thread function
> > * to re-throw existing exception, but with further info about the
> > error (e.g. "bad_alloc happened when fryding the swoorf"). This is
> > because lowest-level exceptions have no further info about the context
> > in which they happened, and that is useful, and C++ has no call stack
> > in exception objects .
> > * there's a loop whose whole body can fail, but next iteration still
> > should happen, usually after reporting the error. Example: a server-
> > kind-of-a-program, who has a client serving loop, and serving one
> > client request failed.

>
> Well that last one is hardly rare. *Most programs today are
> servers, I think.
>
> I stop the propagation in the following for performance
> reasons:
>
> cmw_request
> getRequest (uint8_t byteOrder
> * * * * * * , sock_type sock)
> {
> * static ReceiveBuffer<SameFormat> localbuf(4096);
> #ifdef ENDIAN_BIG
> * static ReceiveBuffer<LeastSignificantFirst> otherlocalbuf(4096);
> #else
> * static ReceiveBuffer<MostSignificantFirst> otherlocalbuf(4096);
> #endif
>
> * uint8_t clientFormat;
> * Read(sock, &clientFormat, 1);
> * try {
> * * if (clientFormat == byteOrder) {
> * * * localbuf.sock_ = sock;
> * * * while (!localbuf.GotPacket()) ;
> * * * return cmw_request(localbuf);
> * * } else {
> * * * otherlocalbuf.sock_ = sock;
> * * * while (!otherlocalbuf.GotPacket()) ;
> * * * return cmw_request(otherlocalbuf);
> * * }
> * } catch (::std::exception const& ex) {
> * * clientFormat == byteOrder ? localbuf.Reset() :
> otherlocalbuf.Reset();
> * * throw;
> * }
>
> }


I don't think you should count this as "stopping propagation", as you-
re-throw.

You should further consider using Alexandrescu/Martinean's excellent
scope guard for such things. That would give you e.g.

cmw_request
getRequest (uint8_t byteOrder
, sock_type sock)
{
static ReceiveBuffer<SameFormatlocalbuf(4096);
#ifdef ENDIAN_BIG
static ReceiveBuffer<LeastSignificantFirstotherlocalbuf(4 096);
#else
static ReceiveBuffer<MostSignificantFirstotherlocalbuf(40 96);
#endif

uint8_t clientFormat;
Read(sock, &clientFormat, 1);
ON_BLOCK_EXIT_OBJ(byteOrder ? localbuf : otherlocalbuf,
&buffer_class::Reset());
if (clientFormat == byteOrder) {
localbuf.sock_ = sock;
while (!localbuf.GotPacket()) ;
return cmw_request(localbuf);
} else {
otherlocalbuf.sock_ = sock;
while (!otherlocalbuf.GotPacket()) ;
return cmw_request(otherlocalbuf);
}

+1 for Paavo's remark. Use RAII, that gets you more time for good
things in life .

Goran.
 
Reply With Quote
 
Ebenezer
Guest
Posts: n/a
 
      12-12-2011
On Dec 12, 12:24*am, Paavo Helde <(E-Mail Removed)> wrote:
> Ebenezer <(E-Mail Removed)> wrote in news:3937da31-10c3-4eea-9105-
>
> > The exception catching allows me to make some variables
> > static that would otherwise be allocating and releasing
> > memory from the heap each time the function is called.
> > It is kind of experimental, but so far so good.

>
> This is just lack of RAII. Why don't you just put a Reset() call in the
> destructor of ReceiveBuffer?
>


I think you may have a point(s) in the other thread and I'll
have to do some digging on that later. So it seems easier to
reply here.
I'm intentionally avoiding RAII here in order
to reuse resources. I don't think calling Reset in the dtor
would help. (I can't think of other places where I avoid
RAII.)

 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      12-12-2011
On Dec 12, 11:50*am, Ebenezer <(E-Mail Removed)> wrote:
> On Dec 12, 12:24*am, Paavo Helde <(E-Mail Removed)> wrote:
>
> > Ebenezer <(E-Mail Removed)> wrote in news:3937da31-10c3-4eea-9105-

>
> > > The exception catching allows me to make some variables
> > > static that would otherwise be allocating and releasing
> > > memory from the heap each time the function is called.
> > > It is kind of experimental, but so far so good.

>
> > This is just lack of RAII. Why don't you just put a Reset() call in the
> > destructor of ReceiveBuffer?

>
> I think you may have a point(s) in the other thread and I'll
> have to do some digging on that later. *So it seems easier to
> reply here.
> I'm intentionally avoiding RAII here in order
> to reuse resources. *I don't think calling Reset in the dtor
> would help. *(I can't think of other places where I avoid
> RAII.)


Perhaps Paavo was a bit too quick with his suggestion... You don't
__need__ to destroy ReceiveBuffer. You can merely have an object whose
destruction calls Reset() on the buffer (Reset() should be a no-fail
operation, which seems a good guess). So you have best of both world:
resource reuse that you hold dear, and application of RAII for simpler
code.

That said, it looks like you could get your resource reuse by changing
ReceiveBuffer to receive the buffer it operates on from the outside.
(I am guessing that the expensive resource is said buffer that is on
the heap, and that Reset is dirt-cheap otherwise.)

Note: function you've shown isn't thread-safe due to the use of the
static. I don't know if it matters, but if it does, you should look
for thread-local storage on your platform.

Goran.
 
Reply With Quote
 
Ebenezer
Guest
Posts: n/a
 
      12-12-2011
On Dec 12, 6:06*am, Goran <(E-Mail Removed)> wrote:
> On Dec 12, 11:50*am, Ebenezer <(E-Mail Removed)> wrote:
>
>
>
>
>
> > On Dec 12, 12:24*am, Paavo Helde <(E-Mail Removed)> wrote:

>
> > > Ebenezer <(E-Mail Removed)> wrote in news:3937da31-10c3-4eea-9105-

>
> > > > The exception catching allows me to make some variables
> > > > static that would otherwise be allocating and releasing
> > > > memory from the heap each time the function is called.
> > > > It is kind of experimental, but so far so good.

>
> > > This is just lack of RAII. Why don't you just put a Reset() call in the
> > > destructor of ReceiveBuffer?

>
> > I think you may have a point(s) in the other thread and I'll
> > have to do some digging on that later. *So it seems easier to
> > reply here.
> > I'm intentionally avoiding RAII here in order
> > to reuse resources. *I don't think calling Reset in the dtor
> > would help. *(I can't think of other places where I avoid
> > RAII.)

>
> Perhaps Paavo was a bit too quick with his suggestion... You don't
> __need__ to destroy ReceiveBuffer. You can merely have an object whose
> destruction calls Reset() on the buffer (Reset() should be a no-fail
> operation, which seems a good guess). So you have best of both world:
> resource reuse that you hold dear, and application of RAII for simpler
> code.
>
> That said, it looks like you could get your resource reuse by changing
> ReceiveBuffer to receive the buffer it operates on from the outside.
> (I am guessing that the expensive resource is said buffer that is on
> the heap, and that Reset is dirt-cheap otherwise.)


That's correct. Thanks for the reminder about scope guard.
I have to think about that and your arguments here further.

>
> Note: function you've shown isn't thread-safe due to the use of the
> static. I don't know if it matters, but if it does, you should look
> for thread-local storage on your platform.
>


Yes, I'm aware of that. The program is currently single-threaded.
I've thought about the possibility of makings it use two threads.
(It is the middle tier of a 3-tier system.) One thread would handle
requests from the front tier and the other thread would handle
responses from the back tier. I don't think changing the program in
that way would be a problem as far as the statics in this function.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Exception propagation in C James Harris C Programming 63 02-17-2012 10:38 PM
Exception Propagation / Copy Constructors better_cs_now@yahoo.com C++ 3 06-18-2009 09:47 PM
Tool for static analysis of C++ exception propagation Brendon Costa C++ 0 11-03-2007 10:23 AM
while executing my client program i get the exception javax.naming.LinkException: [Root exception is javax.naming.LinkException: [Root exception is javax.naming.NameNotFoundException: remaining if plz anybody know how to solve this problem then mahesh Java 0 03-08-2007 12:26 PM
RMI Boundary, Package Visibility, and Exception Propagation robertbrown1971@yahoo.com Java 5 08-26-2005 05:19 AM



Advertisments