From: wij on
>From a different site, a programmer asked for proper coding standard
(error handling) for a common program scenario:

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

I thought it would be very difficult to throw std::exception classes
to handle all thinkable possible exceptional condition. This opinion
has wide
effect to C++ programs.

My argument is that the catch handler won't be able to tell what had
actually
happened and handle it properly. E.g.

initialize();
while(true) {
try {
Message msg,out;
try { receive(msg); }
catch(const std::exception& e) {
// Instead of rethrow or ignore, what can be done here reliably
to handle
// std::exception or others?
}
process(msg,out);
send(out);
}
catch(const std::exception& e) {
// Instead of rethrow or ignore, what can be done here reliably to
handle
// std::exception or others?
}
}

Say if I caught std::invalid_argument from receive(msg), does it
really mean
msg is invalid? The same argument for others e.g.
domain_error,length_error,
out_or_range,range_error,overflow_error,.., and underflow_error.
If the std::invalid_argument is caught in the second catch handler
above,
the picture would be even more complex.

So a coding standard forbids using throw and favors return is simply
practical
from this point view. Instead, most programs using throw is
potentially
buggy.


--
[ 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 2, 3:51 pm, w...(a)seed.net.tw wrote:
> >From a different site, a programmer asked for proper coding standard
>
> (error handling) for a common program scenario:
>
> initialize();
> while (true) {
> Message msg,out;
> receive(msg);
> process(msg,out);
> send(out);
>
> }
>
> I thought it would be very difficult to throw std::exception classes
> to handle all thinkable possible exceptional condition. This opinion
> has wide
> effect to C++ programs.
>
> My argument is that the catch handler won't be able to tell what had
> actually
> happened and handle it properly. E.g.
>
> initialize();
> while(true) {
> try {
> Message msg,out;
> try { receive(msg); }
> catch(const std::exception& e) {
> // Instead of rethrow or ignore, what can be done here reliably
> to handle
> // std::exception or others?

I don't know, it's your problem. You failed to receive message, what
do you want to do about it?

> }

You placed that try/catch block rather badly. You try to receive, that
fails, but you try to process msg. That doesn't seem right. This is
because you caught the exception too early.

> process(msg,out);
> send(out);
> }
> catch(const std::exception& e) {
> // Instead of rethrow or ignore, what can be done here reliably to
> handle
> // std::exception or others?
> }

I don't know, it's your problem. You failed to receive message, what
do you want to do about it?

>
> }
>
> Say if I caught std::invalid_argument from receive(msg), does it
> really mean
> msg is invalid?

You really have to ask the person who decided to throw
invalid_argument from receive. There is no general response to that
question. But in general, you should not throw such a general error.
Instead, you should throw an exception object that explains the error
in best possible terms.

> The same argument for others e.g.
> domain_error,length_error,
> out_or_range,range_error,overflow_error,.., and underflow_error.
> If the std::invalid_argument is caught in the second catch handler
> above,
> the picture would be even more complex.
>
> So a coding standard forbids using throw and favors return is simply
> practical
> from this point view. Instead, most programs using throw is
> potentially
> buggy.

No, not really. A counter example:

bool receive(MSG_TYPE& msg);

if (!receive(msg))
{ // What happened? Was some argument invalid, was there overflow...?
// from one bool, you don't know, just like you don't know
// from std::exception.
}

Understanding errors when they happen is not easy regardless of
mechanism you use, but exceptions easily offer a better way of
explaining the error than error-return, simply because you can create
a full-fledged object that contains any info you might want. With
error-return, getting competent error info is much, much more work.

At any rate, you should not be throwing base exception types, they are
equivalent to

if (!f()) now_what();

But, enough talk. Here's what you could do instead:

class receive_error ... {...};
// be more specific, if you wish (you should be)
class send_error ... { ... };
// etc.

initialize();
while (true)
{
try
{
Message msg,out;
receive(msg);
process(msg,out);
send(out);
}
catch(const exception& e)
{
log_reception_cycle_error(e);
}
}

void log_reception_cycle_error(const exception& e)
{
// use exception.what() to log textual representation
std::cout<<"something went wrong: "<<e.what()<<endl;

// you may use dynamic_cast to get to a specific exception type,
e.g.
if (dynamic_cast<const receive_error*>(&e))
lor_receive_error(dynamic_cast<const receive_error&>(e))
}

You might use multiple catch clauses instead of a function, too. Or,
you can use mix-in derivation to attach your specific interface to
exception classes and then dynamic_cast to get that info. Or you can
use boost::exception to arbitrarily "enrich" info carried by the
exception object.

IOW, you can do all sorts of things to get as finely-grained error
info as you wish. Achieving the same with error-return is way too much
harder.

Goran.


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

From: Randy on
On Jun 2, 9:51 am, w...(a)seed.net.tw wrote:

[snip]

>
> I thought it would be very difficult to throw std::exception classes
> to handle all thinkable possible exceptional condition. This opinion
> has wide
> effect to C++ programs.
>
> My argument is that the catch handler won't be able to tell what had
> actually
> happened and handle it properly. E.g.
>

[snip]

> Say if I caught std::invalid_argument from receive(msg), does it
> really mean
> msg is invalid? The same argument for others e.g.
> domain_error,length_error,
> out_or_range,range_error,overflow_error,.., and underflow_error.
> If the std::invalid_argument is caught in the second catch handler
> above,
> the picture would be even more complex.
>
> So a coding standard forbids using throw and favors return is simply
> practical
> from this point view. Instead, most programs using throw is
> potentially
> buggy.
>

So how would the situation be any different if the called function
returned an error code of, say for example, -3?

The bottom line, IMHO, is that a called function's use of either
exceptions or return codes must be documented in order to know what
they mean. Neither has any inherent meaning in and of itself, only
what the function defines them to mean.

Randy.


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

From: Francis Glassborow on
wij(a)seed.net.tw wrote:
>>From a different site, a programmer asked for proper coding standard
> (error handling) for a common program scenario:
>
> initialize();
> while (true) {
> Message msg,out;
> receive(msg);
> process(msg,out);
> send(out);
> }
>
> I thought it would be very difficult to throw std::exception classes
> to handle all thinkable possible exceptional condition. This opinion
> has wide
> effect to C++ programs.
>
> My argument is that the catch handler won't be able to tell what had
> actually
> happened and handle it properly. E.g.
>
> initialize();
> while(true) {
> try {
> Message msg,out;
> try { receive(msg); }
> catch(const std::exception& e) {
> // Instead of rethrow or ignore, what can be done here reliably
> to handle
> // std::exception or others?
> }
> process(msg,out);
> send(out);
> }
> catch(const std::exception& e) {
> // Instead of rethrow or ignore, what can be done here reliably to
> handle
> // std::exception or others?
> }
> }
>
> Say if I caught std::invalid_argument from receive(msg), does it
> really mean
> msg is invalid? The same argument for others e.g.
> domain_error,length_error,
> out_or_range,range_error,overflow_error,.., and underflow_error.
> If the std::invalid_argument is caught in the second catch handler
> above,
> the picture would be even more complex.
>
> So a coding standard forbids using throw and favors return is simply
> practical
> from this point view. Instead, most programs using throw is
> potentially
> buggy.
You have not made your case. If you can return an error code you can
throw and equally descriptive object (actually good design will allow
the object to be more descriptive. BTW only the most naive programmer
thinks that exceptions are limited to the standard exception classes.

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

From: Pedro LamarĂ£o on
w...(a)seed.net.tw wrote:

> Say if I caught std::invalid_argument from receive(msg), does it
> really mean
> msg is invalid?

It should.

To argue that the thrower might actually be mistaken or lying is not
to argue against the communication mechanism, but rather to reflect on
a fundamental problem with communication itself.

If we receive the EINVAL return value from a function, does it really
mean the argument is invalid?

There is no difference between returning objects or throwing objects
in respect to how much meaning this exchange has to the sender or
receiver.

--
P.

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