C++ Logo

std-discussion

Advanced search

Re: Are Exceptions deeply flawed?

From: Brian Bi <bbi5291_at_[hidden]>
Date: Wed, 7 Aug 2019 16:16:56 -0500
On Wed, Aug 7, 2019 at 4:06 PM Brian Bi <bbi5291_at_[hidden]> wrote:

> On Wed, Aug 7, 2019 at 3:10 PM Dmitry via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> I really don't want to create temporary files anymore, since that implies
>>> removing them at some point. So I really need memfds. So I can't do your
>>> first
>>> point.
>>>
>> What will you do if this feature is not available (your program is
>> running on older kernel)?
>>
>>
>>> Sorry, you don't get to change the API. Using the API as-is was the big
>>> problem of your post. If you can change my API to make it better and
>>> report a
>>> more structured set of information, then the same can be done too for
>>> exceptions.
>>
>> That is really interesting and that is what I cannot fully understand,
>> can you please elaborate how exactly it can be done via exceptions? Of
>> course, in a maintainable way (a way that can easily accommodate
>> adding/removing sub-errors *as well as adding new direct/indirect
>> callers* of the function in the future), without relying on
>> documentation nor on comments etc...?
>>
>>
>>>
>>> Your solution requires that at some point in the call stack, the error
>>> condition be consumed and then either augmented or handled. Nothing in
>>> that
>>> requires using return values, global/thread-local values (like errno) or
>>> exceptions. All three are possible.
>>>
>> All three are possible, not all of them are as visible and explicit as
>> return-values.
>>
>>
>>> What you're arguing for is sanely designed API and handling error
>>> conditions
>>> as close to the error locus as possible. I don't dispute that: that's
>>> the
>>> proper and only way to handle errors. What I will agree with you is that
>>> using
>>> exceptions makes it to easy *not* to do it, since you can simply
>>> "forget" to
>>> handle, then let the error pass on to your caller. When using return
>>> values,
>>> the error condition will often be "in your face" and you'll have a hard
>>> time
>>> ignoring it.
>>>
>>> But C++ does not dictate what you must do. You don't like exceptions? Or
>>> don't
>>> feel comfortable writing code with it, like me? Then don't use them. But
>>> don't
>>> ask that they be removed from the language. That's not going to happen.
>>>
>>
>> Yes, I, probably, agree with you.
>> But, should not then exceptions be discouraged from using exactly as
>>
>> - bare new/malloc (in favour of make_unique/make_shared)
>> - or void * (in favour of type-rich programming)
>> - or default implicit constructors
>>
>> are discouraged now?
>>
>
> I could get on board with the idea that we should discourage people from
> using exception handling in situations where return codes would be a
> *better* solution but you have not established that return codes are *almost
> always better* than exceptions for *almost all programmers*. This is
> quite different from the situation with smart pointers versus manual memory
> management.
>
> I think exceptions are only compelling in situations where some condition
> occurs that the caller may not be able to handle. As an example, an
> iterator that accesses data from a file may, during an execution of
> operator++, encounter an I/O error. At a high level, this may have been
> caused by a network disconnection, interruption by a signal, or various
> more obscure causes. Now the iterator may have been passed as an argument
> to a parser library - the library consumes bytes from the iterator and
> generates tokens as output. The parser wouldn't know what to do about the
> I/O error either. If an exception had been thrown by the iterator, it may
> bubble up to the application that is using the parser library, which might
> (having already handled the signal) simply continue the parsing, or check
> for a network disconnection and ask the user to check whether a cable is
> unplugged, and do whatever other recovery steps are necessary.
>
> I think this is an example where using return codes doesn't add any value,
> because the only thing the parser is going to do is forward the return code
> - it does not need to add any context in order for the caller to handle the
> exception. Note also that the question of the probability of the
> "exceptional" events occurring is not relevant here, except perhaps in a
> performance-sensitive context. Whether you want to make that iterator throw
> an exception on an I/O error, or return expected<char, E>, regardless of
> the fraction of the time that the error path is taken, is a stylistic
> choice. Either way, the caller will either know what to do about the
> condition, or bubble up the error to its caller. In the case with the
> exceptions, the intermediate caller that doesn't know how to handle the
> error doesn't need to have any extra code, but can be written
> "optimistically".
>
> In addition - as someone who has worked on a code base where exceptions
> are banned - I have to say that I don't buy the "exceptions lead to crashes
> in production" logic. If an exceptional condition occurs, then either you
> know how to handle it, or you don't. In the case where you don't, what
> happens when you get the error code you don't know how to handle? At worst,
> the program ignores it and continues to execute, possibly taking actions
> that make no sense, writing bogus data to your database, etc. At best, you
> decide to crash the program and someone gets paged (hopefully you have some
> load balancer so the other servers can handle requests while you debug the
> server that crashed).
>
> The idea that at least with return codes, you can know at compile time
> that there's something you haven't accounted for, is interesting but I
> believe it has its issues as well. There will be cases where sloppy
> programmers will just write a `default:` that propagates the error code
> (which is equivalent to not handling an exception), or which logs the error
> and then swallows it (which is equivalent to `catch (...) {}`, but by
> definition, you cannot know whether this is a sensible thing to do or
> whether it is necessary to crash the program). In fact, I assume that in
> many cases you are going to do this despite the fact that I have full
> confidence that you are a good programmer---because the caller may have
> enough context to know that, given the manner in which it is using the
> callee, a certain error code cannot occur at runtime. But then, like you
> said, you may update the library that contains the callee, and suddenly
> that error can occur, and now your code is broken, with no hint from the
> compiler.
>
>
>> Even if the answer is no, should not we add expected<> (for symmetry or
>> as mechanism that complEments exceptions) into the standard?
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
>
>
> --
> *Brian Bi*
>

Forgot to mention - all of the points I've made are points that have been
made many times by many different people. The same goes for your points.
Still the controversy continues. Effectively, this is one of those
"religious wars" in the world of computing, like whether to use tabs or
spaces. It's fun to talk about, but the result is predictable: no, it's not
time to deprecate exceptions.
-- 
*Brian Bi*

Received on 2019-08-07 16:19:09