On 23/02/2023 17:10,
Mut...@dastardlyhq.com wrote:
> On Thu, 23 Feb 2023 15:02:56 +0100
> David Brown <
david...@hesbynett.no> wrote:
>> On 23/02/2023 11:34,
Mut...@dastardlyhq.com wrote:
>>> I would still consider a crash to be a bug. Undefined would just be returning
>>
>>> rubbish.
>>
>> Undefined behaviour means there is no define behaviour - crashing is
>> entirely plausible. It doesn't matter what /you/ think about it. The C
>> standard is quite clear about this - if you pass a valid argument to
>> isdigit(), as specified in the standard, you'll get a valid result. If
>> you pass something invalid, all bets are off and whatever happens is
>> /your/ problem.
>>
>> This is so fundamental to the whole concept of programming that I am
>> regularly surprised by people who call themselves programmers, yet fail
>> to comprehend it. A function has a specified input domain, and a
>
> Sorry, I get tired of people resorting to "undefined" as some kind of get
> out clause for some badly written API crashing whole program. isdigit() is a
> yes/no function. If it is a valid digit it returns 1 else it returns 0
> regardless. Crashing is a bug. End of.
Sorry, I get tired of people who think /their/ ideas of how languages
work is somehow correct, despite how it contradicts the actual
definition and implementations of the language.
You can argue that this is how the function /should/ work until you are
blue in the face. It doesn't change the simple facts about how it
/does/ work.
As Ben said, it's fine to question if the design choices of the C
standard library functions were the "best" choices (for whatever value
of "best" you want to pick). But there is no point in arguing with reality.
>
>> maybe you'll get a crash. Why you think calling isdigit() with an
>
> Oh ok. How about this then?
>
> int i;
> ++i;
>
> The result is undefined. Presumably you think ++ crashing the program is
> an acceptable outcome?
>
Sure.
I greatly prefer a warning from the compiler that there is a bug in my
code. And I don't expect the compiler to go out of its way to cause a
crash - I expect it to generate efficient code as best it can. But with
a bug in the source code I can't expect the compiler to somehow generate
"correct" code.
And I /like/ the fact that a C implementation is allowed to crash the
program when you try to execute undefined behaviour. That's what allows
you to have tools like sanitizers - compiler this with gcc or clang with
the undefined behaviour sanitizer enabled, and the program /will/ crash
at that point (along with an error message). That makes it easier to
find the bug.
>> invalid input should have some guarantees is beyond me. "Garbage in,
>> garbage out" applies to behaviour, not just values, and has been
>> understood since Babbage designed the first programmable mechanical
>> computer.
>
> Garbage out != program crashes.
>
Garbage out includes behaviour.
You seem to have fallen for the myth that nonsense data values are
somehow not as bad as nonsense control flow - that undefined behaviour
should be allowed to give incorrect results (not that there are any
/correct/ results possible) but not give unexpected control flow
changes. This is a very seductive concept - even the C standards
committee fell for it, making "Annex L - Analyzability" that
distinguishes between "bounded undefined behaviour" and "critical
undefined behaviour".
The problem is, it is bogus. That is why no one has ever tried to
implement anything in Annex L (or at least, no one has succeeded).
Bugs propagate. Invalid data spreads - causing more trouble, including
control flow faults.
int arr[100];
int i = foo(x);
arr[i] = 123;
If "foo()" is specified to return a value between 0 and 100 for an
argument between 0 and 1000, and you pass x equal to -1, does it matter
if "foo(-1)" crashes, or returns a random value outside of 0 to 100 ?
You are screwed either way. You have a bug in your code. You failed to
follow the specifications of the function, and things will go wrong.
Maybe the write will cause an immediate crash. Maybe it will overwrite
the return address on the stack, causing a leap into the unknown.
There's no way of telling.
>> So yes, there is a bug - it's in /your/ code if you pass an invalid
>> value to the function.
>
> BS.
So tell us, whose fault is it that you have not followed the
specification for the function? Your cat's ?
>
>> implementation of the <ctype.h> classification functions involves lookup
>> tables, and it is quite reasonable for a negative value to lead to
>> things going horribly wrong.
>
> So when did out of bounds array accessing become "undefined" in your world
> then rather than a bug?
>
It became "undefined behaviour" when the C standard said it was. You
don't even have to access the object - simply calculating the out of
bounds address is undefined behaviour (except that you can calculate -
but not dereference - one past the end of the array).
If you try to execute undefined behaviour, you have a bug in the code -
since the behaviour is not defined, it cannot possibly match the
behaviour you want, and is therefore a bug.
If you have a bug in your code, the code will be doing something that
you did not intend - you could argue that since you have not defined the
behaviour the code actually exhibits, then it is executing undefined
behaviour.
The concepts of "bug" and "undefined behaviour" are strongly related.