5 ms·
See this is where undefined got lost somewhere. As a layman undefined appears to mean a specific thing here. "undefined by the specification because it does wha
by somat 3y ago
See this is where undefined got lost somewhere. As a layman undefined appears to mean a specific thing here. "undefined by the specification because it does whatever the hardware does" in this context it should never mean "can not happen because it is undefined by the specification". Heck, I don't think it should mean that in any context. whenever a thing is undefined, it is almost always because there is varying hardware that the specification is trying to accommodate.
- inetknght 3y ago> As a layman undefined appears to mean a specific thing here. "undefined by the specification because it does whatever the hardware does" in this context it should never mean "can not happen because it is undefined by the specification". Actually, undefined means "undefined by the specification". It doesn't matter what the hardware does. The specification allows the hardware to do whatever it wants. It's perfectly valid to wipe your hard drive if you trigger undefined behavior.
- deleted 3y ago[deleted]
- dunham 3y agoI also wouldn't expect "undefined" to be consistent within a single compiler implementation. The optimizer is free to make different instances behave differently.
- Someone 3y agoA single compiler can even seem inconsistent. A conforming compiler is allowed to completely remove undefined behavior like this: if((n << 64) == 0) { println("Hi!\n"); } if((n << 64) != 0) { println("Hi!\n"); } If it were implementation-defined, it would have to compile it to the equivalent of println("Hi!\n");
- deleted 3y ago[deleted]
- mike_hock 3y agoThankfully, the standard has seen fit to specify what exactly "undefined" means so you're not left to arbitrarily interpret only the bare word "undefined" in some sort of "layman" way.
- hansvm 3y agoUnthankfully, the definition is so vague as to be totally useless from a programming perspective. Avoid invoking UB, or all hell breaks loose. [0] Separately, I don't think their point was that they were speaking as a layman, but rather that the loose definition they gave is historically accurate, easier to reason about, and what a working programmer not versed in the nuances of UB would expect. The fact that UB has its current definition is indicative of "undefined [getting] lost somewhere." [0] https://kristerw.blogspot.com/2017/09/why-undefined-behavior-may-call-never.html https://kristerw.blogspot.com/2017/09/why-undefined-behavior...
- deleted 3y ago[deleted]
- taway1237 3y agoThe definition is pretty precise, compiler can do whatever it wants with UB. That's not very helpful or useful, but the standard is very explicit about that.
- mike_hock 3y ago> definition is so vague as to be totally useless from a programming perspective. Avoid invoking UB, or all hell breaks loose. How useful it is from a programming perspective is moot because this is the only possible definition if you want a) A language that is powerful enough it can violate the invariants the compiler establishes and upholds in the runtime environment and then (necessarily) assumes are being upheld, and b) any meaningful optimizations at all. What's not reasonable in C is the extent to which stuff lazily gets shoved under the UB umbrella, but the concept itself is not avoidable if you give the programmer enough leeway to conjure up arbitrary pointers out of thin air (but even much less would necessitate UB). What's vague to the extent of being totally useless from a specification perspective is the idea that you can "reason about" something that is undefined (and undefinable). Sure, historically, the original authors had some vague concept of a "portable assembler" in mind. That was a mistake that got rectified since people most definitely wanted b). We have a distinction between "implementation-defined" and "undefined."
- sebazzz 3y ago> undefined by the specification because it does whatever the hardware does No, that's called implementation defined, isn't it?
- ComputerGuru 3y agoNo, implementation defined refers to the compiler implementation, which wouldn’t be the source of behavior here.
- mike_hock 3y agoThat distinction is meaningless. The compiler controls the instructions it generates for the hardware.
- kps 3y agoWhen this comes up, I like to quote Dennis Ritchie on `noalias`: “the committee is planting timebombs that are sure to explode in people's faces”; “a license for the compiler to undertake aggressive optimizations that are completely legal by the committee's rules, but make hash of apparently safe programs”, and consequently: “[It] must go. This is non-negotiable. [...] It negates every brave promise X3J11 ever made about codifying existing practices, preserving the existing body of code, and keeping (dare I say it?) ‘the spirit of C.’” This is what ‘undefined behavior’ turned out to be, so it's clear to me that the consequences of the definition were not understood at the time.
- tialaramex 3y agoDennis is correct about there being timebombs, but the problem was the timebombs were already planted, by him and his colleagues. X3J11 codified them via the "Undefined Behaviour" mechanism, but the alternative isn't to keep K&R C and "not have" undefined behaviour, you just leave a gaping hole in the language. Foundationally C is unsound. For its purpose this made real sense - who cares about soundness, we need to ship Unix ASAP? But with unsound foundations nothing built upon them can be sound itself. ANSI and eventually ISO C finds a way to write the unsound language down formally but doing so doesn't fix it, Mother Nature isn't fooled by words. In places where WG14 declined to write formal language excusing the unsound nonsense (such as provenance rules), there's still unsound nonsense, it's just not written in the ISO document. Again, Mother Nature doesn't care, programs with either kind of unsound nonsense malfunction, the fact that one kind is written down on paper and the other isn't makes no practical difference.
- Rexxar 3y agoA lot of this "undefined behaviour" should have been "implementation defined" or "unspecified behaviour" in my opinion. I don't know why they chose "undefined behaviour" in this case. It was a long time ago, they probably weren't aware it would lead to such problems.
- mike_hock 3y agoSHL masks the shift count, PSLLW/D/Q overshifts "correctly." While that part of the specification predates MMX, they may very well have had the possibility in mind that shifts might be accomplished by multiple instructions with different behavior (if we're gonna give them this much credit). But one way or the other, it's useful now for auto-vectorization.
- marcosdumay 3y agoOn the original meaning, it was more because the actual result depended on what data you had, the value of your registers, what part of the processor pipeline encountered the problem, what other processes you had and what they were doing, and some other impossible to predict stuff. Also, a lot of it could easily be promoted to implementation dependent (this is what you are describing) at the 90's without any problem. But, of course, the modern interpretation is complete bullshit.
- deleted 3y ago[deleted]
- paulmd 3y ago> in this context it should never mean "can not happen because it is undefined by the specification". Even worse, undefined behavior doesn’t just mean “what happens next isn’t defined by the specification”, it is defined, and it’s “anything the compiler wants to happen or that might make the compiler’s life simpler or emit more efficient code”. It's not that there's no rules about what might be emitted, it's that the standard does explicitly say what happens next. And what is specified is an unlimited pass to reorder or transform any input source code that performs this undefined operation, since it was nonsensical anyway. The “undefined” part is the thing that you did, it's the input not the output. The compiler’s output is defined, and it’s “the compiler can do whatever it wants". And that's actually probably the only thing that could make the situation worse! It can return a NOP;RETURN; and continue executing code instead of throwing an exception, or generate any other output for this function that makes its life easier, without let or hindrance by ordering or visibility, or by any relation to the input source code, in a reign of terror that makes a smashing blog post. It is valid to emit fdisk because you aliased a variable in an unreasonable portion of the code. It is valid to return 1 or null or anything else immediately and without notice, regardless of how this affects your expected invariants about data safety or code behavior. Etc. this is, of course, a wildly terrible and terrifying decision to make and Ritchie was absolutely right about that. It's mostly only because compilers have stayed somewhat sane about the code they do emit that this hasn't all come crashing down, but, they get smarter every year.
- bitwize 3y agoI believe that in the before times, "undefined behavior" meant something could be valid in certain contexts, and erroneous in others (as opposed to "implementation-defined" in which something sensible must be done but it's not clear exactly what). For example, null-pointer indirection has meaning if you're banging bits on the bare metal; it means fetch from (or store to) location 0. But most user-space programs on virtual-memory machines don't use location 0, so null is reserved as an invalid pointer/sentinel value. Many architectures for which C compilers exist trap if you try to access an address outside the bounds of an explicitly allocated buffer; the Symbolics Lisp machines had a C environment in which all pointers were "fat": they contained both a pointer to a Lisp object (typically a vector) and an offset from the beginning of that object. So the semantics of memory accesses in C are meant to accommodate those architectures as well as ones in which memory is assumed to be one big array of fixed-size integers and you can read or write wherever.
- IvyMike 3y agoThis can still bite you. Because an aggressive compiler will probably do constant optimization. And the software guy who optimizes 1<<32 might have a different notion of what to do than guy designing the hardware would do. For example, the SUNW compiler sometime around the year 2000. As me how I know.