Live data from Hacker News

Everything in C is undefined behavior

blog.habets.se

521–530 of 748 posts

Re: Everything in C is undefined behavior

#521
post #324

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…

This is all assuming that the code is not invoking undefined behaviour. If the code is invoking undefined behaviour, GCC and clang are both well within their rights to say 'none of the rest of our documentation applies' (and have historically done so on bug reports).

Re: Everything in C is undefined behavior

#522
a good case can be made that use of C++ is a SOX violation

So Linus was right? But for a second reason too:

C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it, to the point where it’s much, much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do _nothing_ but keep the C++ programmers out, that in itself would be a huge reason to use C.

That is, accepting C++ code from programmers who use C++ could be a SOX violation ;-)

Re: Everything in C is undefined behavior

#523

Earlier quoted context omitted.

Which is totally fine and expected for any decent programmer. Casting pointers is clearly here be dragons territory.

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…

> 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.

PCs yes, but there are many other things C is compiled to for which this is not true.

Re: Everything in C is undefined behavior

#524
post #397

Earlier quoted context omitted.

> that can easily be solved by a minute or two on godbolt... Unfortunately it's not that simple when it comes to UB. If the snippet in question does in fact exhibit UB then there's no guarantee whatever Godbolt shows will generalize to other programs/versions/compilers/environments/etc.

That's very funny to me. A) x is always removed. B) no, it's never removed if volatile. But neither person can prove what a compiler will actually do, despite claiming they'll always act a certain way given 5 lines of code.

No, claim A is 'x may be removed by a conforming C compiler'. Whether any given version of a given compiler actually does so in any given circumstance is a different question (the answer being: probably not, because while this is undefined behaviour it's not likely something that is going to be flagged as such by a compiler's optimizer. Also, from some testing with GCC and forcing a null point dereference, it seems like volatile at least does win in that case with the current version of it x86, and it dutifully emits the null pointer dereference and then the 'ud2' instruction instead of the rest of that execution path).

Re: Everything in C is undefined behavior

#525

Earlier quoted context omitted.

You know what JIT means, right? It means that is is not compiled from the start and indeed runs on a bytecode interpreter until the JIT compiler kicks in.

The java JIT has produced sufficiently fast code for all but the most demanding of HPC applications for going on 20 years. I realize keeping up with new developments can be difficult but the out of date java performance memes are entirely ridiculous by now. Meanwhile half the world appears to run on cpython of all things.

Yes, the JIT compiler compiles code. Yes, the results are good. That does not change the fact that the JVM still has and uses a bytecode interpreter, which the comment I replied to disputed.

Re: Everything in C is undefined behavior

#526

Earlier quoted context omitted.

The "anything can happen" means that the compiler can simply silently refuse to emit the code does the access. Documenting that the instructions to access will always be eliminated makes it easier to predict what will happen.

Can you unravel this further (for those of us who don’t know compilers)? I’ve always assumed access past the end of an array can’t always be detected in C, so I don’t see how those instructions could be eliminated. For example, a dynamically linked library that takes in a pointer, and then writes to the 10 ints after it—whether or not this behavior is defined is determined after that library is compiled, right?

> I’ve always assumed access past the end of an array can’t always be detected in C, so I don’t see how those instructions could be eliminated.

"Can't always be detected" is jut a different way of saying "Can sometimes be detected".

Upon detection, I'd rather that the compiler still emit the instructions, not elide the code altogether.

Re: Everything in C is undefined behavior

#527
post #468
post #458

Earlier quoted context omitted.

Previously discussed here: https://news.ycombinator.com/item?id=33770277 UB supersedes volatile, once the compiler hits UB then all bets are off. Compilers can and do optimize out UB branches, which is almost never what you want... yet here we are.

From that thread: https://news.ycombinator.com/item?id=33770905 >> The moment you enter a compilation unit (assuming no link optimizations) with a state which at some point will run into undefined behavior all bets are of. [...] Yes, UB can "time travel" > Close, but not quite. This is a common misconception in the reverse direction. > Abstractly, what UB can do is performing the inverse of the preceding instructions…

Sure, but in this case the volatile accesses are part of the undefined behaviour and so they're not outside of the blast radius.

Re: Everything in C is undefined behavior

#528
post #107
post #87

Earlier quoted context omitted.

Except in C, validation of user input can in itself be an exploit vector.

That’s true in other languages as well. Any programmatic task can end up being an exploit vector.

Yeah, but only in C* can those errors end up as more UB.

* terms and limits may apply.

Re: Everything in C is undefined behavior

#529

Earlier quoted context omitted.

It's a fix that removes the most pointy part of UB. "Going past the end of the array results in addressing arbitrary values" I can live with. "Going past the end of an array results in anything happening" is a hard sell.

Are you talking about creating a pointer (more than one item) past an array, or dereferencing that pointer? Both are currently UB. For the former, I kinda get it. It may need to be there for cases like with segmented address space where p+10 could actually be a value less than p, for the eventually generated assembly. Maybe it should be fine to create such a pointer, but have it be "indeterminate value" or whatever,…

I'm not saying that the result of the dereference be known, I'm saying that the instructions to do the dereference be always emitted.

Right now, if a dereference results in UB, the compiler may omit it entirely.

Re: Everything in C is undefined behavior

#530

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…

> 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. PCs yes, but there are many other things C is compiled to for which this is not true.

C isn't a programming language. It's not even portable assembly. It's a vague suggestion of a program that might or might not be feasible to run on a target computer and the compiler and other diagnostic tools are under no obligation whatsoever to help you find out what, if anything, is wrong with your program. It's user hostile and should be relegated to the bad old days.
Post reply on HN