Earlier quoted context omitted.
Yes, but undefined behaviour is undefined behaviour, and that behaviour can legally be that the code is not emitted at all, volatile (or any other side effect) or not. (and compilers do reason about undefined behaviour when optimising, so this isn't necessarily a completely theoretical argument, though I don't know whether the in compiler's actual logic which of 'don't optimise volatile' or the 'do assume undefined b…
Volatile wins. GCC calls that out [0] - volatile means things in memory may not be what they appear to be, and that there are asynchronous things happening, so something that may not appear to be possible, may become so, because volatile is a side-effect. So about the only optimisation allowed to happen, is combining multiple references. Clang is similar: > The compiler does not optimize out any accesses to variables…
Everything in C is undefined behavior
371–380 of 748 posts
Re: Everything in C is undefined behavior
#372Earlier quoted context omitted.
Only if there would be no side-effects. Which there are.
No this is irrelevant for making this decision
But feel free to run against the various compilers through godbolt. [0] They won't optimise the branch away. Access to a volatile, must be preserved, in the order that they exist. No optimisation, UB or otherwise, is allowed to impede that. Because an access is a side-effect.
Re: Everything in C is undefined behavior
#373Is there a way to avoid undefined behavior Im C then? Could we write a new C compiler that adds some checks and fixes (e.g. raise documented exceptions) to each undefined behavior?
That post is just a hyperbolic rhetorical piece, not even a good technical shade. There are plenty of tools that restrict C into defined behavior subset. HN is just not aware of them. NASA, Aerospace and car industry are big customers, static analyzers and compilers. Good open source ones: Frama-C IKOS (from NASA)
Re: Everything in C is undefined behavior
#374Earlier quoted context omitted.
Removing code paths that the programmer has explicitly laid out in the source code should be made a hard compile error unless the operation has been tagged with an attribute (anyone who wants to add the unsafe keyword to C? ). Another commenter suggested using LLMs, but I disagree. Having clangd emit warning squiggles for unchecked operations (like signed addition) would be a good start.
> Removing code paths that the programmer has explicitly laid out in the source code should be made a hard compile error unless the operation has been tagged with an attribute (anyone who wants to add the unsafe keyword to C? ). Dead code elimination is essential for performance, especially when using templates (this is basically what enables the fabled "zero cost abstraction" because complex template code may genera…
before.
Re: Everything in C is undefined behavior
#375Re: Everything in C is undefined behavior
#376Earlier quoted context omitted.
Yeah, the unaligned accesses aren't going to be atomic unless the hardware supports it. > And in that time, the value of one of the two addresses that the hardware has to load can change. You mean volatile addresses that could spontaneously change in the middle of the reads? Like memory mapped I/O addresses? I would expect these to have stricter access requirements than arbitrary general purpose memory locations. > I…
> Anything that does that is broken and terrible anyway which is why it is undefined behaviour. the optimizer writers have told me consistently that if they can assume you're not doing this thing that's stupid anyway, they can make my code faster. And since I'm not doing that stupid thing anyway, I want my code to be faster.
Compilers can add some custom attributes that encode whatever semantics the badly designed hardware requires. This lets it freely break incorrect code in the small sections that are actually handling those special variables, while allowing the rest of the language to make sense.
Re: Everything in C is undefined behavior
#377Earlier quoted context omitted.
This is a description of an imaginary compiler, evoked by the ANSI/ISO standards documents, which has never existed and will never exist. To understand what the program will do, you just have to understand the compiler behavior on your target platforms. A helpful intuition pump is: imagine the ANSI/ISO specifications simply do not exist; now what? Well, you just continue your engineering practice, the way you would f…
Not imaginary. Eliding checks on nullptr and integer overflow were both implemented, shipped, miscompiled the linux kernel and grew flags to disable them. I expect there are more if one goes looking.
Re: Everything in C is undefined behavior
#378Earlier quoted context omitted.
Author here. > -Acceptance: "Just dont write UB." The point of my article is that this is not possible. This cannot be our end state, as long as humans are the ones writing the code. No human can avoid writing UB in C/C++.
It's honestly not that difficult to be rigorous. The things you mentioned in the blog post are pretty obvious forms of degenerate practices once you get used to seeing them. The best way to make your argument would be to bring up pointer overflow being ub. What's great about undefined behavior is that the C language doesn't require you to care. You can play fast and loose as much as you want. You can even use implici…
Ok, let's try it. I pointed GPT 5.5 at the smallest part of cosmopolitan as I could find in two seconds, net/finger. 299 lines.
describesyn.c:66: q + 13 constructs a pointer that can point well beyond the array plus one element.
C23 6.5.6p9:
> If the pointer operand and the result do not point to elements of the same array object or one past the last element of the array object, the behavior is undefined
Now… you may be trolling, but I do feel like this disproves your assertion. Not you, not me, not Theo de Raadt, can avoid UB.
> the compiler generating code that checks for pointer overflow.
Do you need to check for that specifically? What pointer are you constructing that is not either pointing at a valid object correctly aligned (not UB), or exactly one past the element of an array?
Do you mean for the latter, in case you have an array that ends on the maximum expressible pointer address?
I'm a bit unclear on what you mean by "pointer overflow". From mentioning 56 bit address spaces I'm guessing you mean like the pointer wrapped, not what I pointed to in cosmopolitan, above?
Ok, to be clear that it's not just that one type, if you forgive that one:
net/http/base32.c:64: read sc[0] even if sl=0. I assume this is never called with sl=0, so could be fine.
net/http/ssh.c:355: pointer address underflow? Should that be `e - lp`?
net/http/ssh.c:209/229: double destroy of key. can this code path have non-null members, meaning double free? Looks like it, since line 207 does the parsing and checks that parse worked.
net/http/ssh.c:123: uses memset, which assumes that it sets member variable pointers to NULL (per my post, depending on that means depending on UB), and later these pointers are given to free(), so that's UB.
I won't look deeper into net/http, but presenting just the possibly incorrect remaining comments from jippity:
- ssh.c:211 and parsecidr.c:44: length-taking APIs use unbounded strstr() / strchr(), so explicit n with non-NUL-terminated input can read beyond the buffer.
- tokenbucket.c:77 and tokenbucket.c:92: x >> (32 - c) is UB for c == 0 and for out-of-range c.
- isacceptablehost.c:68: long numeric host labels can overflow signed int b before the function eventually rejects/accepts the host.Re: Everything in C is undefined behavior
#379 struct foo {int i;};
int func(struct foo *x) {return x->i;}
int main() {
int (*funcptr)(void*) = (int (*)(void*)) &func;
struct foo foo = { 42 };
return funcptr(&foo);
}
While this is all kosher per the language lawyers: struct foo {int i;};
int func(void *x) {return ((struct foo *)x)->i;}
int main() {
int (*funcptr)(void*) = &func;
struct foo foo = { 42 };
return funcptr(&foo);
}Re: Everything in C is undefined behavior
#380The problem lies with compilers, not with the language and its specification, or with the creators of the C programming language.
Anyone can write a compiler that transforms all undefined behaviors (UB) into defined behaviors (DB). And your compiler will be used by people, including me.