5 ms·
> The above example will print the value of a, but it won’t be initialized to 123! It certainly could do though. In C, using an uninitialised variable does not
by quietbritishjim 2y ago
> The above example will print the value of a, but it won’t be initialized to 123!
It certainly could do though. In C, using an uninitialised variable does not mean "whatever that memory happened to have in it before" (although that is a potential result). Instead, it's undefined behaviour, so the compiler can do what it likes.
For example, it could well unconditionally initialise that memory to 123. Alternatively, it could notice that the whole snippet has undefined behaviour so simply replace it with no instructions, so it doesn't print anything at all. It could even optimise away the return that presumably follows that code in a function, so it ends up crashing or doing something random. It could even optimise away the instructions before that snippet, if it can prove that they would only be executed if followed by undefined behaviour – essentially the undefined behaviour can travel back in time!
- kazinator 2y agoIn C, it is only undefined behavior to access an automatic object that has not been initialized. Static objects are always initialized, so the situation cannot arise. That leaves dynamic ones, like uninitialized struct members in a malloced structure. Accessing uninitialized dynamic memory means isn't undefined behavior in C. It results in whatever value is implied by the uninitialized bits. If the type in question has no trap representations, then it cannot fail.
- uecker 2y agoUB can not travel back in time in C. Although it is true that it can affect previous instructions, but that code is reordered or transformed in complicated ways is true even without UB.
- kazinator 2y agoIf a compiler can determine that some statement is UB, it can treat that as an assertion that the code is unreachable. All other statements which reach only that code and no other are also unreachable. A compiler's analysis can go backward in time. That is to say, the compiler can build a model of what happens in some section of code over time, and analyze it whichever way it wants. You cannot go back in time from execution time to translation time, but the translator can follow the code as if it were executing it at translation time.
- emmericp 2y agoThe time-travelling UB interpretation was popularized by this blog post about 10 years ago [1]. I'm not enough of a specification lawyer to say that this is definitely true, but the reasoning and example given there seems sound to me. [1] https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633 https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=63...
- uecker 2y agoYes, random blog posts did a lot of damage here. Also broken compilers [1]. Note that blog post is correct about C++ but incorrectly assumes this is true for C as well. [1]. https://developercommunity.visualstudio.com/t/Invalid-optimization-in-CC/10337428?q=muecker https://developercommunity.visualstudio.com/t/Invalid-optimi...
- kibwen 2y agoI'm inclined to trust Raymond Chen and John Regehr on these matters, so if you assert that they're incorrect here then a source to back up your assertion would help your argument.
- uecker 2y agoI am a member of WG14. You should check the C standard. I do not see how "time-travel" is a possible reading of the definition of UB in C. We added another footnote to C23 to counter this idea: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf "Any other behavior during execution of a program is only affected as a direct consequence of the concrete behavior that occurs when encountering the erroneous or non portable program construct or data. In particular, all observable behavior (5.1.2.4) appears as specified in this document when it happens before an operation with undefined behavior in the execution of the program." I should point out that compilers also generally do not do true time-travel: Consider this example: https://godbolt.org/z/rPG14rrbj https://godbolt.org/z/rPG14rrbj
- 2y ago
- ant6n 2y ago> but that code is reordered or transformed in complicated ways is true even without UB. Without undefined behavior, the compiler emits code that has the behavior defined by the code —- the ordering may be altered, but not the behavior.
- uecker 2y agoYes, and with undefined behavior, the compiler has to emit code that has the behavior defined by the code up to the operation that has undefined behavior.
- kazinator 2y agoThat is false. If a compiler determines that some statement has undefined behavior, it can treat it as unreachable, and, transitively, other code before it as unreachable. printf("hello\n"); // this doesn't have to print x = x / 0; // because this is effectively a notreached() assertion
- jstimpfle 2y agoThis is in direct contradiction to what uecker says. Can you back up your claim -- for both C and C++? Putting your code in godbolt with -O3 did not remove the print statement for me in either C or C++. But I didn't experiment with different compilers or compiler flags, or more complicated program constructions. https://godbolt.org/z/8nbbd3jPW https://godbolt.org/z/8nbbd3jPW I've often said that I've never noticed any surprising consequences from UB personally. I know I'm on thin ice here and running risk of looking very ignorant. There are a lot of blogposts and comments that spread what seems like FUD from my tiny personal lookout. It just seems hard to come across measureable evidence of actual miscompilations happening in the wild that show crazy unpredictable behaviour -- I would really like to have some of it to even be able to start tallying the practical impact. And disregarding whatever formulations there are in the standard -- I think we can all agree that insofar compilers don't already do this, they should be fixed to reject programs with an error message should they be able to prove UB statically -- instead of silently producing something else or acting like the code wouldn't exist. Is there an error in my logic -- is there a reason why this shouldn't be practically possible for compilers to do, just based on how UB is defined? With all the flaws that C has, UB seems like a relatively minor one to me in practice. Another example: https://godbolt.org/z/b5j99enTn https://godbolt.org/z/b5j99enTn This is an adaption from the Raymond Chen post, and it seems to actually compile to a "return 1" when compiling with C++ (not with C), at least with the settings I tried. And even the "return 1" for me is understandable given that we actually hit a bug and there are no observeable side-effects before the UB happens. (But again, the compiler should instead be so friendly and emit a diagnostic about what it's doing here, or better return an error). Un-comment the printf statement and you'll see that the code totally changes. The printf actually happens now. So again, what uecker says about observable effects seems to apply.
- deleted 2y ago[deleted]