Earlier quoted context omitted.
No, that would be implementation defined.
No, that's actually UB. The important bit here is "compiler defined" -- UB means the compiler is allowed to assume it never happens while compiling. Consider, for example, an implementation defined function f() -- which can also diverge/crash horribly, etc. If I write if p { print("p is true") } else { g() } if p { f() } Then either we: - print p is true and execute f - do nothing This is true regardless of if f imme…
Everything in C is undefined behavior
591–600 of 748 posts
Re: Everything in C is undefined behavior
#592Earlier quoted context omitted.
Both are wrong. It means "this standard does not constrain the behaviour of code that does this". It's entirely legal for implementations to have predictable behaviour, documented or not, for code that is undefined by the standard. In their quest for maxxing benchmark performance they generally choose not to, but there's really nothing in any standard that stops you from making an implementation that prioritises safe…
Every implementation so far has predictable behavior in all cases. Sometimes the rules for predicting it are very obscure. But it's all fully defined within the compiler's binary code. And none of them link to nasal portals.
Moreover, this is at best an incredibly pedantic point, not something that changes how programmers need to approach UB. You can't review the source code of a compiler that hasn't been written yet.
Re: Everything in C is undefined behavior
#593Earlier quoted context omitted.
The first example is dereferencing an integer pointer. That is a valid operation. Now if that pointer isn't valid (and being unaligned is one of many reasons it could be invalid) then calling the function with that invalid pointer will be UB. An honest discussion would be something more like 'dereferencing pointers can lead to UB on invalid pointers. Here are N examples of that. Maybe avoid using pointers. Maybe cons…
There is an important distinction here to the technical meaning of UB that is lost to many. UB simply means the operation you are intending to perform has no defined semantic under the ISO C specification. That is all. Understand what this means but do not read further into it. It is easy to read further into this as you have and many do, and come to incorrect conclusions, and think this MUST result in incorrect beha…
"Accessing an object which is not correctly aligned" - this is UB
"As an example of this, take this code: ..." - this (code) is not UB.
Is this incorrect somehow?
You could interpret the second sentence as 'under the assumption of an unaligned pointer, let's look at what this seemingly innocuous (and correct) code does.'
But that's not what they did. They presented that code as if it's incorrect (following the whole premise of the article 'Everything in c is UB'). That's what the whole article does, they take a topic with real concerns, then present 'normal' code, and then imply the code is the issue (and therefore the language), not the premise.
You know what would be better, show an example that clearly shows the complete path for the premise to the issue. Ie show some code that generates an unaligned pointer and then uses it. Why did the author not do that? Surprise, because it's actually pretty hard to write code that's 'guaranteed' unaligned behavior.
int foo[10];
int *bar = (int *)(((int)&foo) + 1);
Is this unaligned access? You don't know because you don't know the size of int. (Not to mention it looks ridiculous. By only showing 'reasonable' code as the example, the article suppresses the common 'uh just don't do that' criticism.)And in fact the ambiguity of alignments and sizes is the whole point - they are given the privilege/footgun of being undefined in c so that compilers are easier to write. It's very debatable if this was/is a good idea, but that's where the debate should be, not illusorily ascribed to derefing pointers.
If I'm misunderstanding, please let me know. Specifically, if you're claiming (1) either the literal code in the first box of the article is UB, or (2) please write some literal code that is UB in the vein of the first claim of the article. I think that would help me bridge the gap that we seem to be having.
Re: Everything in C is undefined behavior
#594Earlier quoted context omitted.
In many architectures does not mean you can. The standard is supposed to cover all architectures.
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. Load multiple integers and shift and mask away the irrelevant bits, done. This is exactly what modern architectures already do in hardware. Works, it's just a little slower. This is exactly what the compilers do if you use a packed structure to access u…
Wouldn't the compiler have to assume that every pointer access might be unaligned and do the slow "piece by piece" access every time? It can hardly guess the runtime value of a pointer during compilation.
Re: Everything in C is undefined behavior
#595Earlier quoted context omitted.
How is undefined behavior necessary for this transformation?
IIRC computation of the address is done by computing offset from base pointer as a multiplication in (32-bit) int , (like p + (i * sizeof (Foo)) . The right term might overflow, but due to signed overflow being UB, the compiler is able to assume that it does not, so the transformation to do the arithmetic entirely in (64-bit) pointer space is valid.
This is also a major blocker for auto-vectorization. Can't coalesce a load of a[i], a[i+1], a[i+2], a[i+3] into a load of a[i:i+3] if there's a possibility that `i+1`, `i+2` or `i+3` wrapped around (thus causing your "contiguous" load to be non-contiguous). This is a big reason why you shouldn't use `unsigned` for loop counters, especially if they're going to be used as an index into an address calculation.
Re: Everything in C is undefined behavior
#596Re: Everything in C is undefined behavior
#597Re: Everything in C is undefined behavior
#598Earlier quoted context omitted.
String search algorithms would be one example, where a 64-bit register can be used as a “vector” containing 8x1 bytes.
Where is the part about unaligned pointers?
Re: Everything in C is undefined behavior
#599Earlier quoted context omitted.
Volatile is a type system hack. They should have done a more principled fix, and certainly modern languages should not act as though "C did it" makes it a good idea. The reason for the hack is that very early C compilers just always spill, so you can write MMIO driver code by setting a pointer to point at the MMIO hardware and it actually works because every time you change x the CPU instruction performs a memory wri…
By MMIO semantics do you mean explicit load and store instructions? I’ve never felt that pointer reads or writes were lacking descriptiveness here. I would argue the only surprising thing is that they might be optimized out (which is what volatile prevents). Volatile on a non pointer value is not for MMIO, though, that’s typically for concurrency like with interrupts.
The C and C++ languages would be very slow by modern standards if you insist that reading or writing via a pointer must result in immediate fetches or stores to memory.
> Volatile on a non pointer value is not for MMIO, though, that’s typically for concurrency like with interrupts.
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.
Re: Everything in C is undefined behavior
#600Yes there is tons of surprising and weird UB in C, but this article doesn't do a great job of showcasing it. It barely scratches the surface. Here's a way weirder example: volatile int x = 5; printf("%d in hex is 0x%x.\n", x, x); This is totally fine if x is just an int, but the volatile makes it UB. Why? 5.1.2.4.1 says any volatile access - including just reading it - is a side effect. 6.5.1.2 says that unsequenced…
I think the article's point is that you don't actually have to get weird at all to run into UB. Lots of people mistakenly think that C and C++ are "really flexible" because they let you do "what you want". The truth of the matter is that almost every fancy, powerful thing you think you can do is an absolute minefield of UB.