Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

741–748 of 748 posts

Re: Everything in C is undefined behavior

#741

Earlier quoted context omitted.

> If some architecture traps on unaligned access, then the compiler can and should simply generate the correct code so that it loads the integer piece by piece instead. LMAO what?! The compiler should pessimize each and every memory access everywhere with an alignment check on the pointer and a branch, or forego the efficient memory access method of the platform entirely and just do bytewise loads only?!

Unaligned access. Not every access. Compiler should be able to analyze code, determine alignment invariants and optimize everything it can. If not, __builtin_assume_aligned could help whenever it needs to be made explicit. Alignment should have been part of the type itself to begin with but there's no fixing that now.

So yes, pessimize each and every access. No, that's not acceptable. And no, just because the compiler can get rid of some of the alignment checks where static analysis can prove that the pointer is aligned doesn't cut it.

Yes, making alignment part of the type system would be the correct fix. And yes, that's absolutely still possible since unaligned access is still UB. You're not breaking existing code. You could easily add new pointer types with (static) alignment information.

Re: Everything in C is undefined behavior

#742

Earlier quoted context omitted.

> A clear majority of the UB problems with C could be fixed if the standards committee slowly moved all UB into IB There is no such thing as getting rid of "all UB." What behavior is the implementation supposed to prescribe for a write to an unpredictable garbage address you read from the network? It could overwrite your code. It could overwrite any value anywhere. It could overlap with anything. Prescribing defined…

> What behavior is the implementation supposed to prescribe for a write to an unpredictable garbage address you read from the network? I "The compiler is not allowed to elide a write to a garbage address". Wasn't that easy?

No, because that doesn't mean anything. All the other guarantees the compiler has to make about the other parts of your program have potentially been violated by the write, so the compiler can't guarantee any particular behavior.

Hence, "undefined behavior," of the entire program, not just that particular write.

Re: Everything in C is undefined behavior

#743
post #720

Earlier quoted context omitted.

> Unaligned access being fine in one architecture, but not in others would create separate dialects, regardless of being blessed by ISO C. That doesn't mean unaligned access would need to be UB. It could be implementation defined. Or could just be defined to result in an error on all machines.

Implementation-defined without further constraining the behavior is not much better than undefined. Defining it to always error would add overhead even for proper aligned access on x86, as the generated code would need to explicitly check in many cases.

> Implementation-defined without further constraining the behavior is not much better than undefined.

No, it's a lot better. Because implementations have to define it.

Re: Everything in C is undefined behavior

#744

Earlier quoted context omitted.

If a trap is observable behaviour, then the compiler either needs to add code, that checks for the condition and then traps explicitly or it needs to actually perform the read. Currently it can be optimized out, because it is UB.

I think you misunderstood my suggestion. It isn't that misaligned accesses must either all succeed or all fail. That's not possible in general because of MMIO devices. The suggestion is that each individual access must either succeed or trap. Those are the only possible outcomes, but different accesses can result in different outcomes.

And you misunderstand me. Your proposal means, that the compiler, must emit an individual access with the right values at the right time. If an access may succeed or fail, then the compiler can not just convert it into an aligned read, or not a read at all.

If your proposal includes, that a trapping access gets treated by the compiler as if it didn't and the compiler emits code that performs all kind of side-effects, that are logically independent if it would not trap, before the access, then you are back to undefined behaviour under a different name.

Re: Everything in C is undefined behavior

#745

Earlier quoted context omitted.

If a trap is observable behaviour, then the compiler either needs to add code, that checks for the condition and then traps explicitly or it needs to actually perform the read. Currently it can be optimized out, because it is UB.

You're merely attacking his particular suggestion and using this as an argument to defend UB, when those are completely independent concerns. What people want is for a compiler that assumes that all pointers are aligned to use an aligned store or load instruction whenever the compiler wants to issue such an instruction. There is no need for UB here. In other words, they want the compiler to stick with the decision it…

Yes, I am "attacking" his particular suggestion with the reasoning of this particular UB. I disagree that these concerns are independent, as the reasoning for the UB is often, that any choice per se would be limiting the possible compiler behaviour. It is not a particular choice, that would be limiting, but the act of picking one per se.

> What people want is for a compiler that assumes that all pointers are aligned to use an aligned store or load instruction whenever the compiler wants to issue such an instruction.

That requires a mental model of a compiler, that runs through the code linearly and emits instructions in the order defined by the code. That's not what is happening. Current compilers model the value flow through the code, and then emit a program that happen to output the same values for the valid input.

> In other words, they want the compiler to stick with the decision it made

What instead often happens is, that the compiler doesn't even emit a decision at all, because that is completely irrelevant.

Re: Everything in C is undefined behavior

#746

Earlier quoted context omitted.

> You're holding it wrong. Perhaps you've been holding it wrong for so long and so confidently that you've distorted the world around you -- indeed on MSVC on x86 or x86-64 that actually happened -- but, you're still holding it wrong. Please explain. How would you make the variable backed by a hardware register region? Is this using some sort of linker trick to change where the value lives in memory?

You said it was for concurrency. The feature you want for that in C (and most languages suitable for this problem) is atomic memory ordering, not the volatile type qualifier. Microsoft's platform was x86 only for years, and because Intel's design pays for a lot more memory ordering by default than most, on Microsoft's platforms just "volatile" would kinda work even though it was the wrong thing, so Microsoft explicit…

We were talking about what these features were for when introduced. At the time there were no atomic instructions because there weren’t multiple concurrent execution paths or modern multi layer caching. At the time volatile on a scalar value would only be for preventing optimizations from the compiler assuming linear non-reentrant flow control. I would generally expect that to primarily be used for interrupt handlers in low level code, but posix signal handlers are similar.

Memory mapped registers are typically represented as pointers to volatile structs which I thing correctly represents that the device backing those addresses does not behave like main memory. Reading to or writing from those addresses needs to preserve the -O0 behavior of C where each pointer dereference must be preserved. I just don’t find anything particularly unclear about this, and I certainly don’t see any reason to make the caller have to be extra explicit about it when the reads and writes are already spelled out in the source code.

Post reply on HN