Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

321–330 of 748 posts

Re: Everything in C is undefined behavior

#321
post #231

Earlier 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…

GCC -O1 and clang -O1 will both optimize this function under the assumption that inputs that cause signed integer overflow are never passed: int will_overflow(int a, int b) { int sum = a + b; if (b > 0 && sum

Right, good example, and both GCC and Clang offer well understood parameters for deciding, per compilation unit, what behavior you want for signed overflow (-fwrapv, -fno-strict-overflow, etc), so in reality it's quite far from spooky arbitrary nasal demons.

Re: Everything in C is undefined behavior

#322

Earlier quoted context omitted.

Many, many programmers come to C (and C++) with a lower-level understanding that actually gets in the way here. They understand that all types "are" just bytes and that all pointers "are" just register-sized integer addresses, because that's how the hardware works and has worked for decades. It's perfectly reasonable to expect any load through `int*` to just load 4 bytes from memory, done and done. They get surprised…

> They understand that all types "are" just bytes and that all pointers "are" just register-sized integer addresses, because that's how the hardware works and has worked for decades. I'd clarify this with "They understand that all values are just bytes" . > Meanwhile, the actual computers we have been using for decades have no problems actually just loading 4 bytes through any arbitrary pointer with zero overhead. It…

Turning undefined behavior into implementation defined behavior is rarely a fix, though.

Re: Everything in C is undefined behavior

#323
post #118

Earlier quoted context omitted.

But that seems obvious. You can't load an integer from an unaligned address. It's not only C-level is it. There's no (guarantee across architectures for) machine code for that either.

> You can't load an integer from an unaligned address. You can, and the results are machine specific, clearly defined and well-documented. Ancient ARM raises an exception, modern ARM and x86 can do it with a performance penalty. It's only the C or C++ layer that is allowed to translate the code into arbitrary garbage, not the CPU.

There’s usually not a performance penalty on modern hardware

Re: Everything in C is undefined behavior

#324
post #296

Earlier quoted context omitted.

"volatile" tells the compiler it is _not_ safe to optimise away any read or write, so it can't just optimise that section away at all. > An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2…

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 declared volatile. The number of volatile reads and writes will be exactly as they appear in the C/C++ code, no more and no less and in the same order.

[0] https://www.gnu.org/software/c-intro-and-ref/manual/html_nod...

Re: Everything in C is undefined behavior

#326

Earlier quoted context omitted.

The pointer might be something you forced. The compiler needs to do the right thing but if you set the pointer to an unaligned address because you have information on the hardware you can get this undefined situation with nothing the compiler can do about it.

Any reason the hardware pointer can't be accessed via the packed structure? https://news.ycombinator.com/item?id=48205371

The same reason you probably aren’t adding manual alignment fixes to your code?

Re: Everything in C is undefined behavior

#327
post #129

Earlier quoted context omitted.

Unless your code targets some exotic architecture, like idk x86.

Not really. Wait until the compiler starts vectorizing your code and using instructions requiring alignment (like the ones with A or NT in the mnemonic).

Usually the compiler will probably not generate those

Re: Everything in C is undefined behavior

#328
post #296

Earlier quoted context omitted.

Your first paragraph makes it sound as if the compiler will actually generate two reads of the value of some register, which might lead to unexpected effects at runtime for certain special registers. However, this is not at all what UB means in C (or C++). The compiler is free to optimize away the entire block of code where this printf() sequence occurs, by the logic that it would be UB if the program were to ever re…

"volatile" tells the compiler it is _not_ safe to optimise away any read or write, so it can't just optimise that section away at all. > An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2…

When compiler decides something is UB aka "result of this code is not defined and could be any" it selects the most performant version of undefined behavior - doing nothing by optimizing code away.

Re: Everything in C is undefined behavior

#329

feels like https://xkcd.com/1499/ the only people complaining about being able to do awful things are people that do awful things

- a metal bar always sinks

- unless you are trying to sink it in mercury. then it floats

- unless it is an uranium bar

- go sink uranium bars in mercury yourself

Re: Everything in C is undefined behavior

#330

Earlier quoted context omitted.

Not having unaligned access in the language allows the compiler to assume that, for basic types where the aligment is at least the size, if two addresses are different then they don't alias and writes to one can't change the result of reads from the other. That's a very useful assumption to be able to make for optimization - much more useful than yolocasting pointers in a way that could get you unaligned ones.

> if two addresses are different ... Eh, if the compiler knows that two addresses are different at compile time, it also knows how big the difference is.

Usually this is not the case.
Post reply on HN