From: Francis Glassborow on
Mathias Gaunard wrote:
> On 4 juin, 15:34, Francis Glassborow
> <francis.glassbo...(a)btinternet.com> wrote:
>
>> Now consider a function that calls two functions both of which can fail
>> with an error code return but that cannot directly handle either
>> problem. If you use error returns you start getting ever more
>> complicated error handling as each successive function up the call stack
>> has to decide what the error return meant and wether it can handle it or
>> needs to relay it upwards. With exceptions all this is handled simply
>> and transparently.
>
> I thought it was fairly complicated, but actually it isn't that much
> if you still use destructors. Simply return as soon as you have an
> error and everything still gets cleaned up properly.
>
Yes, but if you use error codes every function has to not only check
them but decide what to relay up the stack. With exceptions it is simple .

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

From: Martin B. on
On 04.06.2010 23:34, Thomas Richter wrote:
>(...)
> I only want to stress the attention to the fact that the old argument of
> "throwing an exception is useful so another level of the code can handle
> it" seems not to be quite true for my application domain.(...)
>
> Exceptions are pretty useful. But for me not exactly for the reason you
> mentioned. It makes code easier to read, and it makes error forwarding a
> lot easier. But I rarely forward errors to have them handled "upwards",
> but to report them "upwards", interrupting all of *my* work without
> leaking resources or keep working on stale data. Most of the exceptions
> I throw cannot be safely resolved in any sane way. Not that I want to
> abort the program, but rather inform the caller "this data is simply
> invalid. Cannot decode, stop here."
>

Interesting point. Maybe that's one reason why I find myself using bare
runtime_error("Message...") more often than not. All the exception does
is "abort" the current operation and handily also provide a little
logging message that tells a bit more.

br,
Martin

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

From: Goran on
On Jun 4, 3:38 pm, w...(a)seed.net.tw wrote:
> > class receive_error : public std::exception { ... };
> > class send_error : public std::exception { ... };
> > class processing_error : public std::exception { ... };
>
> > initialize();
> > while (true) {
> > try {
> > Message msg,out;
> > receive(msg);
> > process(msg,out);
> > send(out);
> > }
> > catch (receive_error& e) {
> > // receive() barfed
> > }
> > catch (processing_error& e) {
> > // process() barfed
> > }
> > catch (send_error& e) {
> > // send() barfed
> > }
> > // other exceptions propagate out
>
> > }
>
> For the revised example program to work. Those thrown objects nearly
> have to be unique to the extent that no other function can throw the
> same error.

No, program will work even if you only throw std::exception, just as
if it will work if you use bool return and e.g. never set errno (or
similar). The problem is that if you use exceptions, if nothing else,
you will know that there was something wrong, and will have error text
explaining what went wrong __at the place error happened__. With e.g.
bool return value, you only know that a particular function did not
work. If that function calls three other functions, you have no idea
what went wrong, nor you even have text explaining the error.

You should really post most comprehensive example of what complete
code should look, error handling and reporting included. If you do
that, I bet you that I can come up with a piece of code that does the
exact same thing, uses exceptions and is shorter in lines of "running"
code (basically, clean of conditional logic that will be all over the
place in your code). Is that OK?

Goran.


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

From: wij on
On 6月7日, 上午6時16分, Goran <goran.pu...(a)gmail.com> wrote:
> On Jun 4, 3:38 pm, w...(a)seed.net.tw wrote:
>
>
>
> > > class receive_error : public std::exception { ... };
> > > class send_error : public std::exception { ... };
> > > class processing_error : public std::exception { ... };
>
> > > initialize();
> > > while (true) {
> > > try {
> > > Message msg,out;
> > > receive(msg);
> > > process(msg,out);
> > > send(out);
> > > }
> > > catch (receive_error& e) {
> > > // receive() barfed
> > > }
> > > catch (processing_error& e) {
> > > // process() barfed
> > > }
> > > catch (send_error& e) {
> > > // send() barfed
> > > }
> > > // other exceptions propagate out
>
> > > }
>
> > For the revised example program to work. Those thrown objects nearly
> > have to be unique to the extent that no other function can throw the
> > same error.
>
> No, program will work even if you only throw std::exception, just as
> if it will work if you use bool return and e.g. never set errno (or
> similar).

Surely throwing std::exception can work (too much complicated to
be practical). Take another String member function for instance:

int String::insert(size_t index, const String& str);

Possible error equivalents are EINVAL EFBIG ENOMEM ELOOP(str is self)
Throwing them, one should consider the possibility of being
misinterpreted.

Many would say throwing exceptions is simple and elegant.
Yes it is, but not until the program contains catch codes.

Throwing error is not equivalent to returning error, rather it is
equivalent to a throw (with insignificant object) and an errno
like global variable.

>The problem is that if you use exceptions, if nothing else,
> you will know that there was something wrong, and will have error text
> explaining what went wrong __at the place error happened__. With e.g.
> bool return value, you only know that a particular function did not
> work. If that function calls three other functions, you have no idea
> what went wrong, nor you even have text explaining the error.

Error message is somewhat not the point being discussing.
Besides, using dynamic string inside a throw class is questionable.

> You should really post most comprehensive example of what complete
> code should look, error handling and reporting included. If you do
> that, I bet you that I can come up with a piece of code that does the
> exact same thing, uses exceptions and is shorter in lines of "running"
> code (basically, clean of conditional logic that will be all over the
> place in your code). Is that OK?
>
> Goran.
>

The complete code for the server-like program scenario can be lengthy
if expanded to real compilable form. But I guess my intent should be
made clear by now.

initialize();
while (true) {
Message msg,out;
receive(msg);
process(msg,out);
send(out);
}

In general there are quite some exceptional conditions that are
normally supposed to be handled in the server-like program loop:

Reply by return (or the equivalent):
ENOSPC no buffer space
EINVAL this may by dynamic (e.g. format error)
EINTR signal interrupted
EPIPE peer down
ETIMEDOUT preset timeout
ENAMETOOLONG long pathname
EFBIG too large data, similar to ERANGE
ELOOP too many links or as mentioned above

I don't see any possible catch program can be both simple and elegant
as
is usually declared. Note the baseline is correctness.


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

From: Ulrich Eckhardt on
wij(a)seed.net.tw wrote:
> On 6月7日, 上午6時16分, Goran <goran.pu...(a)gmail.com> wrote:
>> On Jun 4, 3:38 pm, w...(a)seed.net.tw wrote:
>>
>>
>>
>> > > class receive_error : public std::exception { ... };
>> > > class send_error : public std::exception { ... };
>> > > class processing_error : public std::exception { ... };
>>
>> > > initialize();
>> > > while (true) {
>> > > try {
>> > > Message msg,out;
>> > > receive(msg);
>> > > process(msg,out);
>> > > send(out);
>> > > }
>> > > catch (receive_error& e) {
>> > > // receive() barfed
>> > > }
>> > > catch (processing_error& e) {
>> > > // process() barfed
>> > > }
>> > > catch (send_error& e) {
>> > > // send() barfed
>> > > }
>> > > // other exceptions propagate out
>>
>> > > }
>>
>> > For the revised example program to work. Those thrown objects nearly
>> > have to be unique to the extent that no other function can throw the
>> > same error.
>>
>> No, program will work even if you only throw std::exception, just as
>> if it will work if you use bool return and e.g. never set errno (or
>> similar).
>
> Surely throwing std::exception can work (too much complicated to
> be practical). Take another String member function for instance:
>
> int String::insert(size_t index, const String& str);

Funny that you bring up a string class as example, which would be utterly
useless without exceptions. Consider a constructor taking a char* or an
overloaded operator+ not throwing when they go out of memory. Basically, it
means that you can not sensibly use them, which severely restricts the
usability of your string class.

> Possible error equivalents are EINVAL EFBIG ENOMEM ELOOP(str is self)
> Throwing them, one should consider the possibility of being
> misinterpreted.
>
> Many would say throwing exceptions is simple and elegant.
> Yes it is, but not until the program contains catch codes.
>
> Throwing error is not equivalent to returning error, rather it is
> equivalent to a throw (with insignificant object) and an errno
> like global variable.

I don't understand where you see the similarity with a global errno variable
from. If you mean that, equally to errno, you can't always be sure where it
came from, then I don't see how that differs from returning an int as
errorcode.


> The complete code for the server-like program scenario can be lengthy
> if expanded to real compilable form. But I guess my intent should be
> made clear by now.
>
> initialize();
> while (true) {
> Message msg,out;
> receive(msg);
> process(msg,out);
> send(out);
> }
>
> In general there are quite some exceptional conditions that are
> normally supposed to be handled in the server-like program loop:
>
> Reply by return (or the equivalent):
> EINTR signal interrupted

This one is more or less a glitch in the interface of Unix systems. This one
can and should be handled exactly where it happened:

while(true) {
int e = some_sys_call(...)
if(e==0)
return; // success
if(e==EINTR)
continue; // try again
throw system_error("some_sys_call", e);
}

> ELOOP too many links or as mentioned above

I don't understand this error type.
> ENOSPC no buffer space
> EINVAL this may by dynamic (e.g. format error)
> EPIPE peer down
> ETIMEDOUT preset timeout
> ENAMETOOLONG long pathname
> EFBIG too large data, similar to ERANGE
[...]
> I don't see any possible catch program can be both simple and
> elegant as is usually declared. Note the baseline is correctness.

All these should probably close the connection. Some of these might merit
sending an error response and then optionally closing the connection.
Again, while you provided info about the errors you expect, you omitted how
you intend to handle these errors individually, which is crucial! So I'll
have to guess...

try {
while(true) {
try {
Message in = connection.receive_request();
Message out = process(in);
connection.send_response(out);
} catch(processing_error const& e) {
// handle processing errors by replying with an
// according error code stored in the exception
connection.send_error_response(e.error_id);
}
}
} catch(std::exception const& e) {
connection.close();
}


Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


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