[ Crossposted to comp.lang.c since we need some C lawyers ;-) ]
On Sun, 09 Apr 2017 14:53:01 GMT
I guess I wasn't clear enough. By "anything" I mean anything related to the context.
So if I'm translating some C code (note that "translating" doesn't necessarily mean
compiling ; C is usually compiled but there are C interpreters) relevant stuff are
- C standard.
- Translator documentation. For example by using the appropriate options one may get
additional guarantees beyond the C standard like -fwrapv gcc supports and
which makes signed integer oveflow defined.
- If one uses headers or functions or macros , etc. which do not appear in the C
standard then these must be defined somewhere else like in some other standard
or they must be part of some library and be defined in the documentation of the
library.
- There may more which is relevant. I don't see how Forth or assembly are relevant
unless one calls an external process which is written into one of these languages.
Mathematics is relevant only to the extent that the related documentation or
standard(s) says that it's relevant. For example it follows from the C standard
that for integers x and y of the same type T , if the mathematically correct result
of x+y fits into T then that's what x+y evaluates to. But if it didn't specify
this then one should not have assumed that the mathematical definition of + is
relevant even if they felt that it would be the natural way to define C's +
operator.
The underlying principle is that one must have some rational reason to expect
code to behave in a certain way. For example if I have C code which includes
frooboz(123) ;
I must have have some rational reason to expect this to translate without errors and
do something specific I have in mind. Since the C standard does not define frooboz()
, this reason must come from somewhere else. So we definitely need some stronger
concept than WUB. What counts as "pretty natural definition" for signed integer
oveflow (or anything else) seems subjective to me and I don't even see how it is
relevant whether someone is a Forth programmer or assembly programmer (of which
architecture ?) or mathematically inclined. Even in mathematics , what x+y means
depends on the context. The definition is different if x and y are elements of ℤ
(integers) as opposed to say ℤ/5ℤ .So what is defined in some context depends
on the context rather than the overall knowledge and experiences one has. To get to
one of your favorite examples , if your C code has signed integer oveflow what's
your rational reason to expect that it will do something specific (like wraparound)?
The reason cannot be the C standard because the C standard says it's undefined
behaviour. If your compiler documentation does not say that it will produce assembly
which does wraparound then you have no reason to expect the code to behave in a
predictable manner so that code needs to be changed. You say above "to get rid of
the undefined behaviour without losing functionality and performance". Without
rational reason to believe that your code will do what you want then you don't
actually have functionality ; if it seems to behave the way you want then it is just
a coincidence and the behaviour may go away without warning like if you use a
different version of compiler. So there's nothing to lose (apart perhaps from
occasions where you urgently want to achieve something and you're willing to kludge
it) , either you fix the code or you have nothing you can depend on.
> 2) Nasal demon fans want license to produce nasal demons for every
> undefined behaviour. E.g., in the general case both gcc and
> Clang/LLVM generate code for 2s-complement arithmetic with
> wraparound for signed integer addition, subtraction, and
> multiplication, so you might classify it as WUB. Nasal demon fans
> still want to keep signed integer overflow undefined even in those
> compilers so that they make use of it for "optimizations".
As I said in a previous post , I don't believe there are "nasal demon fans". As for
wanting license I find this puzzling because I don't believe they need a license.
For example , one might decide to write a C compiler which supports all other parts
of the C standard but not the for statement. One does not need any kind of license
to do this , one simply needs (from a moral point of view) to be honest about what
they offer. And then other people can decide if they want to use the compiler or
not. But if they decide to use it then their expectations must be based on what the
compiler does claim to offer , not on what they would wish it to offer. They might
wish that it also supported the for statement but since it doesn't claim to do so
then they shouldn't use for in their code (if they want to translate their code
with this compiler).
By the way , regarding gcc and signed integer operations , what do you mean "general
case" ? My impression is that without using -ftrapv or -fwrapv then oveflow for
signed integer operations is undefined.
Are you translating this with a C translator which defines in its documentation
things like "mapped memory location" ? If not then these terms are meaningless (in
the specific context of using this specific code with this specific translator) , it
is SUB and you can't have any expectations whatsoever regarding how this code will
behave. I certainly wouldn't. I take it you would ? If yes on what basis ?
> >> 3) Complete correctness proofs of programs are outside the competence
> >> of nearly all programmers (and pretty pointless, because they would
> >> prove only the correctness wrt the specification, which itself may be
> >> buggy).
> >>
> >> Now, to write a C program that is guaranteed to never exercise
> >> undefined behaviour requires competences on the level 3.
> >
> >Not in the slightest. Consider the following piece of C code :
> >
> > int is_leap_year(unsigned int year) {
> > return 1 ;
> > }
> >
> >It's trivial to see that this is defined but , judging from the function's
> >name , it's almost certainly buggy. A complete correctness proof is many
> >orders of magnitude harder than simply ensuring defined behaviour.
>
> I don't think it is trivial to see that this is defined.
Well , I'm not going to locate and quote all the parts of the C standard which
support my view but I have no doubts that it is defined.
> I once
> <
2015May...@mips.complang.tuwien.ac.at> wrote:
>
> |It seems to me that
> |
> | if ((size_t)(dest-src) < len)
> |
> |is a more efficient way to test whether dest is inside [src, src+len).
> |
> |Of course, since this code contains more than three tokens, it is
> |likely to contain undefined behaviour
>
> That was mostly in jest, but a post or two later, someone explained
> that yes, this code is undefined. So while I do not see anything
> undefined about the code you posted, just let the language lawyers at
> it, and they will point it out.
Ok , we'll see what the language lawyers say.
> In any case, in your example it is trivial to see that it does not
> satisfy the requirement that is implied by the name, so even if it
> really is trivial to see that it is defined, it only shows that both
> correctness and definedness are trivial to determine for trivial
> programs.
My point was simply to provide a counterexample to your statement
Now, to write a C program that is guaranteed to never exercise
undefined behaviour requires competences on the level 3.
I provided a reference above and it does not support your claims that this
is what caused the bug. Do you have a reference which says otherwise ?
> It is telling that you do not understand how the nasal-demon
> interpretation of C allowed the compiler to "optimize" the
> memset()/bzero() away. So much for Andrew Haley's claim that it is
> "not difficult" to write "well-defined" C, and your defense of that
> stance.
I understand what you're claiming but you haven't provided any reference that this
is what caused the bug in the case of OpenSSH.
> >I couldn't tell you off the top of my head but I'm sure you could get the
> >answer on comp.lang.c very quickly. Looking at the big picture , it could
> >be that C is not a suitable back-end for Forth after all even if you got
> >lucky for a number of years and your code (which presumably was exhibiting
> >SUB) worked as intended.
>
> I think that nasal-demon C is not a suitable language for anything.
I use it all the time with perfectly predictable results. I have my complaints
but they are not caused by undefined behaviour.
> > Note that this may turn out to be an opportunity for
> >Forth : it may be that Forth itself is a more suitable back-end than C for other
> >programming languages
>
> Yes.
>
> >A
> >*constructive* thing to do (as opposed to complaining) would be to describe
> >what guarantees with regard to C pointer comparisons on top of the C standard
> >would be needed to do what you want to do. Then you could ask on comp.lang.c
> >or some compiler mailing list whether these additional guarantees can be
> >offered by using some appropriate flag and if not how easy would be to implement
> >them as an extension.
>
> If you think that's a promising approach, go ahead. My experience is
> that they always tell you to go to the C standards committee.
Before you go to the C standards committee you need to have a specific proposal. I
take it that for C to be a suitable back end for implementing Forth , you want
comparison of C pointers pointing to different objects to be defined. Could you
provide a set of axioms that such comparisons ought to satisfy to be adequate for
your purposes ? If not then even if C compiler writers or the C standards committee
wanted to accommodate you , they have no way to do so. You can't expect them to read
your mind , can you ? "Do the natural thing" is not a meaningful definition. I don't
think that the following from your paper is a meaningful definition either :
C* A language (or family of languages) where language constructs correspond
directly to things that the hardware does. E.g., * corresponds to what a
hardware multiply instruction does. In terms of the C standard, conforming
programs are written in C .
I couldn't provide such a set of axioms because I've never implemented a Forth so I
don't know in what ways standard C as a back end is lacking.
> >Undefined behaviour is an unfortunate side effect of 3 factors :
> >
> >1. The desire to allow implementors optimisations.
> >2. Inability to reconcile previous (i.e. before the standard) existing practices
> > therefore any attempt to define the behaviour more narrowly would unfairly
> > privilege some implementations (or architectures) over others.
> >3. The desire to not make the standard too large.
>
> That was all fine and dandy in the good old days of PCC and early GCC,
> but in recent years the compiler maintainers went insane and use them
> as justification for miscompiling (they call it "optimizing") as many
> programs as possible, with some exceptions, in particular, standard
> benchmarks. Paying customers are probably also not treated as badly
> as the rest of us; hmm, so nasal demons may be part of the business
> models.
If it's SUB then it's impossible to miscompile it because correct compilation is not
defined.
> > But noone *likes* undefined behaviour , it is just a trade off.
>
> The GCC and Clang compiler maintainers love it. For them reason 2 and
> 3 don't apply, yet with every release they miscompile more and more
> cases that are undefined in the standard for reasons 2 and 3; e.g.,
> signed integer overflow.
gcc provides 2 different options for getting predictable behaviour for signed
integer overflow. So this contradicts your statement.
> >If
> >programmers get convinced to avoid undefined behaviour then this ultimately
> >will make code more predictable not less.
>
> So you love nasal demons, too.
I avoid SUB so they are indifferent to me. For the point I was making , you snipped
relevant context. I said
The talk of nasal demons is to drive home the point (especially to new
programmers) that when dealing with undefined behaviour (that is SUB) there's no
"reasonable" behaviour one can expect therefore *** Just say no *** .If
programmers get convinced to avoid undefined behaviour then this ultimately will
make code more predictable not less.
To add to the above , as a metaphor which is used as an educational tool , I
consider it unfortunate because it ignores the fact that a computer exists and
operates in the real world so it can only cause things which are physically
possible. There are other ways to drive home the point that SUB is unpredictable
without mentioning physical impossibilities.
> Many programmers are convinced. But because there is actually no good
> way to write code without undefined behaviour, we will get programs by
> convinced programmers that have fewer undefined behaviours, but it
> will still be there; and the next release of the compiler breaks some
> code, the convinced programmers get busy fixing it, and the next
> release breaks some more code. Bottom line: slightly faster
> benchmarks, more programs that break, and more work for the C
> programmers without any benefit.
There is a way to write code without SUB and that is to be familiar with the
standards and documentation which is relevant to the code one writes. Bugs may exist
of course but this would be the case just as much even with no undefined behaviour.
[...]
> >But then there are always some
> >stubborn ones like yourself or
> >
http://www.open-chess.org/viewtopic.php?f=5&t=2519 where Robert Hyatt
> >insists that SUB should still do what he wants just because it did in the past.
>
> So you think that using strcpy to do an overlapping backwards copy is
> SUB, i.e., "not defined according to *anything*". Interesting.
I read the thread a while ago and I can't be bothered to reread it but I don't think
that Hyatt said that he was using a C library which , as an extension to the C
standard , defined strcpy() for overlapping objects. If that's the case then the
behaviour was not defined according to anything relevant to the code he was writing
so I would classify it as SUB and I don't believe that he had any rational reason to
expect a specific behaviour (but he thought otherwise). What one might consider
"natural" or useful behaviour for strcpy() does not affect the definition of SUB. I
will present a more general principle :
For the tools you use , you cannot expect what has not been promised to you.
A C compiler is a tool and so is a C library (whether it's the standard C library or
some other) ; they were written by humans. If those humans do not tell you for
example "we made sure that strcpy() copies correctly even overlapping objects" then
you have no rational reason to expect it.
--
This, of course, is a straw man. As the Stanford Encyclopedia of Philosophy observes
Moral relativism has the unusual distinction - both within philosophy and outside
it - of being attributed to others, almost always as a criticism, far more often than
it is explicitly professed by anyone.
http://www.mathpages.com/home/kmath557/kmath557.htm