A note for C programmers

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: A note for C programmers

Post by wgarvin »

bob wrote: The standards does not adequately define "undefined behavior".
(the precise definition of undefined behavior from the spec)
I'm curious what you WOULD consider an adequate definition. Anyway, its the one we've got to work with. :)
So it can ignore the situation, to behaving in a documented way (both of which make sense) to terminating the compilation with a message. No mention of demons flying out one's nose or anything else.
Almost.. it says it can ignore the situation with unpredictable results. That doesn't seem so stop people from trying to predict them anyway, even though the standard specifically says they can't rely on anything.
bob wrote: So how about we get back to planet earth.

In reality, using strcpy() with overlapping operands is not undefined, because I can take the source and enumerate the possible outcomes for any pair of arguments. That's as it should be. Adding outcomes not possible from the actual code is senseless...
Again, I think that is a dangerously wrong idea of what programming is about. You're not writing an x86 binary here; you're writing a source program in a programming language and you seem unwilling to acknowledge that you thus have to follow the rules of that programming language if you want to end up with a reliable and future-proof program.
Rein Halbersma
Posts: 741
Joined: Tue May 22, 2007 11:13 am

Re: A note for C programmers

Post by Rein Halbersma »

bob wrote: For example, what happens when you compute x / 0.0 on Intel? Depends on whether you have allowed divide by zero and enabled infinity. On a Vas? program exception. Good example of undefined. Can't say which without knowing details. Once I know the CPU and in the case of intel, the floating point control word, I can tell you exactly what will happen, whether you like it or not is a different issue, but one you can handle within your program.

To claim that it can do something completely unrelated is utter nonsense.
The Intel assembly instruction corresponding to x / 0.0 might guarantee to do what you want it to do. But the C statement x / 0.0; may or may not be translated to said assembly instruction depending on the optimization level of your compiler. You clearly don't like this, but you have to choose from one of the following alternatives

1. Write a draft proposal to the C Standard Committee to close the compiler leeway for this particular case of UB
2. Write the statement in assembly
3. Put up with any compiler that exploits this UB for optimization purposes.
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: A note for C programmers

Post by wgarvin »

I have an alternative explanation for the last few days of this thread that makes it suddenly make sense to me!

Bob doesn't really believe the things he's saying about undefined behavior, but he has figured out that we get indignant and he's having too much fun trolling us to stop! :lol:
Rein Halbersma
Posts: 741
Joined: Tue May 22, 2007 11:13 am

Re: A note for C programmers

Post by Rein Halbersma »

wgarvin wrote:I have an alternative explanation for the last few days of this thread that makes it suddenly make sense to me!

Bob doesn't really believe the things he's saying about undefined behavior, but he has figured out that we get indignant and he's having too much fun trolling us to stop! :lol:
Never attribute to malice that which is adequately explained by stupidity.
rbarreira
Posts: 900
Joined: Tue Apr 27, 2010 3:48 pm

Re: A note for C programmers

Post by rbarreira »

wgarvin wrote:I have an alternative explanation for the last few days of this thread that makes it suddenly make sense to me!

Bob doesn't really believe the things he's saying about undefined behavior, but he has figured out that we get indignant and he's having too much fun trolling us to stop! :lol:
I actually hope you're right. At least it would mean he's not teaching this nonsense to his students.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A note for C programmers

Post by bob »

Rein Halbersma wrote:
bob wrote: For example, what happens when you compute x / 0.0 on Intel? Depends on whether you have allowed divide by zero and enabled infinity. On a Vas? program exception. Good example of undefined. Can't say which without knowing details. Once I know the CPU and in the case of intel, the floating point control word, I can tell you exactly what will happen, whether you like it or not is a different issue, but one you can handle within your program.

To claim that it can do something completely unrelated is utter nonsense.
The Intel assembly instruction corresponding to x / 0.0 might guarantee to do what you want it to do. But the C statement x / 0.0; may or may not be translated to said assembly instruction depending on the optimization level of your compiler. You clearly don't like this, but you have to choose from one of the following alternatives

1. Write a draft proposal to the C Standard Committee to close the compiler leeway for this particular case of UB
2. Write the statement in assembly
3. Put up with any compiler that exploits this UB for optimization purposes.
Or 4. Expect the compiler to do EXACTLY what I wrote. And then let the chips fall where they may.

The compiler CAN do the divide, rather than resorting to demons, smoke, locusts or anything else.
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: A note for C programmers

Post by wgarvin »

bob wrote: Or 4. Expect the compiler to do EXACTLY what I wrote. And then let the chips fall where they may.

The compiler CAN do the divide, rather than resorting to demons, smoke, locusts or anything else.
Unfortunately that's not usually an option you can rely on, these days. It worked back in the 80's when the compilers were too stupid to take advantage of the freedom given to them by the language spec. There are a lot of old-school C and C++ programmers who were used to how things worked back then. But they don't work that way anymore. Well, usually they do, but sometimes they don't, and those programmers then complain, even though the language has always been that way.

Perhaps what we need is a "dialect" spec for modern RISC-like machines, that builds on the C language spec and specifies additional semantics for a lot of the common undefined-behavior cases. Then compiler vendors could implement THAT spec and the programs written to it could safely rely on things that a lot of programmers seem to want to rely on anyway.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A note for C programmers

Post by bob »

wgarvin wrote:I have an alternative explanation for the last few days of this thread that makes it suddenly make sense to me!

Bob doesn't really believe the things he's saying about undefined behavior, but he has figured out that we get indignant and he's having too much fun trolling us to stop! :lol:
Sorry, but I don't argue just to expend time. This is not about "undefined behavior" as much as it is about how a compiler treats that undefined behavior. I believe I should be allowed to add or subtract any two integer values I want. If it overflows, it overflows. It should STILL produce the expected result knowing word length is not infinite. It should NOT produce a random number, or a sine of 45 degrees, or any other arbitrary calculation, it should do no more than EXACTLY what I specified. I've never held the C standards in very high regard for this and other idiotic positions they took. I have not changed that opinion. But now SOME are taking it to new levels. "undefined" no longer means "the result can't be precisely stated because it can vary depending on the underlying architecture, the strings, how much they overlap, how big the word size is, whether the memory is byte addressable, word addressable, or something else, etc." It would seem that SOME here believe that ANYTHING is allowable as opposed to simply doing the right thing. Which, by the way, is exactly what the compiler does in every undefined case I have looked at. strcpy() has done the same until Apple dove in. Etc...

You ask me to build you a house, but you ask me to include some feature that I am not certain will perform as you expect. Can I just give you a big hole in the ground instead? Or say "I can do anything since this is undefined, so here's a toothpick I made from all that lumber."???

this is not being sensible to assume "undefined" means "anything in the universe."
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: A note for C programmers

Post by wgarvin »

bob wrote:With the deranged reasoning here, if one does a BSF instruction and the source is all zero bits, the destination register is undefined. Should the program crash? Because you can always use a "jz" to determine that there were no one bits set and eax has no useful value in it (actually, it is unchanged from its contents prior to executing the bsf).
There's no C language construct that maps to BSF, but just suppose for a moment there was and that the language spec said it was "undefined behavior" to use the value from the destination register after a BSF with all zero source bits. All kinds of weird stuff could happen if the programmer didn't respect that undefinedness.

The compiler might notice that you are assigning the destination register to a variable. If you happened to pass in all zero bits, then the contents of the register are undefined, and so is the variable. So in a branch that uses that variable, it might assume that your source for the BSF was non-zero. It might then delete an if-statement comparing that source with zero.

Another example: the compiler might be able to prove that if reached via a certain control path, the BSF was executed with all zero bits as the input. It might hoist the BSF and subsequent instructions onto each path, and then delete the BSF that produces the undefined result, and any instructions on that path using the result (it might do this because of a partial redundancy elimination pass, for example).


Similar odd-sounding narratives exist for things like shifting into or out of the sign bit in signed ints, dividing INT_MIN by -1, dividing by zero, and so on. So its best to just never do them. Even if it happens to work _today_, on some compilers and some library versions, that is probably a temporary state of affairs. Now that they have a taste for the optimization benefits, it will take a bloody revolution to convince compiler vendors to stop taking advantage of the freedoms that the language has always reserved to them.

You can't reason your way up from how the low-level machine works to how a C construct is going to work, if that C construct happens to invoke "undefined behavior" according to the C language standard. Any reasoning of that sort is fallacious and dangerous. The only way you can know your program is correct is to (1) test it under the specific target platform, with specific compiler, libraries, etc. and then NEVER CHANGE THEM. Or, (2) follow the rules of the language, even arcane ones that offend your sensibilities.
syzygy
Posts: 5557
Joined: Tue Feb 28, 2012 11:56 pm

Re: A note for C programmers

Post by syzygy »

bob wrote:Sorry, we are talking pure C. C as is used in Crafty. Threads DO make sense, there is a native thread library for every machine I have used.
They are compiler and environment specific. They are not pure C89 or C99. There is no reasonable way to argue against this.
Your example fails pretty miserably however.
It does not. Look up "data race" in C11. The example I gave is a data race and it would be trivial to detect. (Well, at least one access must be a write access.) I don't know why are you are talking about different source files, that was not part of my example. (Not that modern compiler/linkers would be bothered by optimising across source files.)

I'm also not talking about Crafty. You said something was impossible. I gave an example where it is trivial. That's it. Now you start turning and twisting, of course, as you always do in such circumstances.