lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] logic vs runtime errors


From: Vadim Zeitlin
Subject: Re: [lmi] logic vs runtime errors
Date: Fri, 7 Sep 2018 19:04:18 +0200

On Fri, 7 Sep 2018 15:32:45 +0000 Greg Chicares <address@hidden> wrote:

GC> On 2018-09-07 13:52, Vadim Zeitlin wrote:
[...]
GC> >  Why do you think that that "logic error" means "error in the internal
GC> > logic"?
GC> 
GC> Because the C++17 standard [22.2p2] says so:
GC> 
GC> | 2 The distinguishing characteristic of logic errors is that they are
GC> |   due to errors in the internal logic of the program.
GC>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 This is just an unfortunate choice of words. I just automatically assumed
that the word "internal" here meant "inside the program and not coming from
the outside world, e.g. user or some device" without stopping to think
about this at all. And even now that I did, I still believe that this was
the intention of the authors of these words. But I realize now that they
were not at all as unambiguous as I thought they were.


GC> Then are you saying that you have seen a case where it's useful to
GC> handle classes logic_error and runtime_error (those classes themselves,
GC> as opposed to their derived classes) differently at the catch site?

 Yes.

GC> Can you give a concrete example?

 I think runtime_errors must be reported to the end user, with as many
details as possible, because they might help the user to actually solve the
problem or, at least, understand where is it coming from. E.g., again, this
is an extremely simple, not to say simplistic, example, but if reading from
a file fails, I definitely want to tell the user which file it was. I also
want the program to continue running if a runtime_error happened because
there is no reason for it not to recover from it.

 OTOH it's useless and confusing to report logic_errors to the user as
there is nothing they can do about those ones anyhow. So for them the most
appropriate error message is to tell the user to report the problem as a
bug (and maybe log all the details in some file that the user would be
asked to attach to the bug report). It is also strongly advisable to quit
the program in case of a logic_error as it may well mean that the internal
state got corrupted in some unrecoverable way.

 Again, I realize that this division is not as universal as I thought it
was, and that some program[mer]s might prefer to avoid reporting all the
details even for the runtime_errors, but at least for me it is quite useful
to be able to distinguish between the 2 cases.


GC> Okay, that can be distilled into a simple rule that I can understand:
GC> 
GC> "Prefer logic_error to runtime_error for precondition violations"

 Yes, I can sign under this.

GC> I.e., in such cases where we're going to write one or the other, write
GC> logic_error instead of runtime_error. But otherwise, most importantly
GC> where we're going to write an assertion, the assertion is perfectly okay:
GC> 
GC>     // in 'math_functions.hpp':
GC>   LMI_ASSERT(0 != denominator); // This is notionally a logic_error.
GC>     // in 'multiple_cell_document.cpp':
GC>   LMI_ASSERT(3 == i_nodes.size()); // Malformed input file: runtime_error.
GC> 
GC> The assertion macro actually throws std::runtime_error in both cases,
GC> and we needn't change that.

 I would change this to conform to the rule above and I wouldn't use
LMI_ASSERT() for the second assert at all as this is not a precondition
that can be reasonably established by caller.

GC> > or, if you prefer, define lmi_precondition_error deriving from it and
GC> > always use this one instead.
GC> 
GC> I read a suggestion like that in a textbook once, and wrote this:
GC> 
GC> ihs_server7702.cpp:    catch(server7702_implausible_input const& e)
GC> ihs_server7702.cpp:    catch(server7702_inconsistent_input const& e)
GC> ihs_server7702.cpp:    catch(x_product_rule_violated const& e)
GC> ihs_server7702.cpp:    catch(server7702_adjustable_event_forbidden_at_issue 
const& e)
GC> ihs_server7702.cpp:    catch(server7702_guideline_negative const& e)
GC> ihs_server7702.cpp:    catch(server7702_misstatement_of_age_or_gender 
const& e)
GC> 
GC> ...which now seems regrettable.

 Yes, I agree. And arguably the existence of domain_error, out_of_range etc
is regrettable, or at least not very useful, as well. But having one type
for all lmi assertions might be useful if you think we might want to
distinguish LMI_ASSERT() check failures from e.g. accessing the vector
using a wrong index using its at() method. I do agree that right now I
don't really see any need for it.

 Regards,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]