13. But if the line with UB isn't executed, then the program will work normally as if the UB wasn't there. 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. 15. If the line with UB is unreachable code, then the program won't crash because of the UB. 16. If the line with UB is unreachable code, then the program will at least stop running somehow and at some point. This…
You have to understand that in the modern understanding of UB as applied by compiler writers, the compiler has every right to assume the program never triggers UB. This means that lines which would be UB if a variable had certain values can be used as proof that the variable doesn't have those values, thereby eliminating checks. For example, if a program looks like this: void foo(int* const p) { if (p!=NULL) { bar(p)…
Falsehoods programmers believe about undefined behavior
61–70 of 233 posts
Re: Falsehoods programmers believe about undefined behavior
#62Earlier quoted context omitted.
> This is nonsense. The line with UB has to be reached for the execution to be undefined. Check the footnote at item 14, it links to a page which shows one example of how a line with UB can be reached (basically: the optimizer can reorder the code so that parts of the line with UB will run much earlier than you'd expect).
UB "making dead code live again" is not an example of UB in dead code making the execution undefined. Yes UB in live code can have surprising effects, including executing dead code.
I think the main reason for this is an if(testSomeState()) { //code with UB } block being optimized to just //code with UB.
Functions which are unreachable, maybe I agree, they can't be executed (without UB somewhere in reachable code). I'm not sure that's true though - if you have UB in your hardware (not your code), you can still execute that code. This is why (at least I was taught) never to leave dead code around. There's this better thing for that called source control you may have heard of...
IF you have perfect hardware, and IF you have perfect logic/compiler and IF you have no UB in your program, then maybe you can guarantee that dead code is really dead, but I'm not really sure you want to heavily define dead code like that.
Just remove it. Especially if it has UB in it to cause more fun bugs...
Re: Falsehoods programmers believe about undefined behavior
#6313. But if the line with UB isn't executed, then the program will work normally as if the UB wasn't there. 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. 15. If the line with UB is unreachable code, then the program won't crash because of the UB. 16. If the line with UB is unreachable code, then the program will at least stop running somehow and at some point. This…
You have to understand that in the modern understanding of UB as applied by compiler writers, the compiler has every right to assume the program never triggers UB. This means that lines which would be UB if a variable had certain values can be used as proof that the variable doesn't have those values, thereby eliminating checks. For example, if a program looks like this: void foo(int* const p) { if (p!=NULL) { bar(p)…
It is true that when foo() is called with a NULL argument, the UB will be realized before bar() has had a chance to run (EDIT: this doesn't actually appear to be true for the given code sample, neither Clang nor GCC elide this NULL check: https://godbolt.org/z/v9v74c3jd, which makes sense as bar() could call exit()).
> Note that it's not executions which trigger UB, it is source code programs that do.
For C, I think this interpretation is directly contradicted by DR #109: https://www.open-std.org/jtc1/sc22/wg14/docs/rr/dr_109.html
> Furthermore, if every possible execution of a given program would result in undefined behavior, the given program is not strictly conforming. A conforming implementation must not fail to translate a strictly conforming program simply because some possible execution of that program would result in undefined behavior. Because foo might never be called, the example given must be successfully translated by a conforming implementation.
Re: Falsehoods programmers believe about undefined behavior
#64> 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. This one came as a surprise to me. Is this really (unconditionally) true? And if so, why? Seems trivial to me to ensure that UB that will never under any circumstance execute will not affect the functioning of an otherwise correct program.
No, it isn't. The line with UB has to be reached in the execution for the execution to be undefined.
Or, here is a better example:
for(int i=0; i > n;) {
}
*p=1;
Here the compiler will assume that the loop terminates, since non-terminating loops without side-effects are UB in C++.Then, since the loop terminates, p will be dereferenced, so it can be assumed that p is never NULL, so any NULL checks for p in this context can be ellided.
This remains valid even if you call this function with an n such that *p=1 is unreachable.
Re: Falsehoods programmers believe about undefined behavior
#65I am always amazed by articles like these. This guy thoroughly covers this topic. I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Is this just an interesting topic or do people actively push the compiler to see what it will do? Maybe I am a boring/simple programmer. :)
> I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Assuming you're working with C or C++, you've never: - Dereferenced a pointer? - written a loop with a signed index? - Accessed an index in an array or a vector? - Used a variable? - Used an optimising compiler? Compilers use undefined behaviour in all of the above scenarios as much as possib…
Re: Falsehoods programmers believe about undefined behavior
#66The biggest problem with UB, as interpreted by C/C++ compilers is the unfounded belief that the spec says that you can assume any path that leads to UB is defacto incorrect and can be ignored. That's the bogus logic required for steps 13-16 to be true. That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - w…
Compiler designers just chose the notion of "obviously user wouldn't invoke the footgun, so any code that would be causes by footgun can be removed"
Re: Falsehoods programmers believe about undefined behavior
#67Earlier quoted context omitted.
No, no, no. UB is a global property of your program. "All bets are off" even at compile time. "Anything at all can happen; the Standard imposes no requirements. The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended." https://blog.regehr.org/archives/213
UB is typically a property of the execution of a program. A program may bump into UB for one set of inputs, but not for an other set.
"If any step in a program’s execution has undefined behavior, then the entire execution is without meaning. This is important: it’s not that evaluating (1<<32) has an unpredictable result, but rather that the entire execution of a program that evaluates this expression is meaningless. Also, it’s not that the execution is meaningful up to the point where undefined behavior happens: the bad effects can actually precede the undefined operation."
Re: Falsehoods programmers believe about undefined behavior
#68Earlier quoted context omitted.
This is an absurd reduction of the current situation. > That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work withou…
Read the gcc mailing list. There is alot of user hostile "fix your broken program" from language lawyers. I think aliasing rules messes up memcpy if you are dogmatic?
Re: Falsehoods programmers believe about undefined behavior
#69Earlier quoted context omitted.
This is an absurd reduction of the current situation. > That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work withou…
Read the gcc mailing list. There is alot of user hostile "fix your broken program" from language lawyers. I think aliasing rules messes up memcpy if you are dogmatic?
> I think aliasing rules messes up memcpy if you are dogmatic?
I'm _not_ dogmatic or a language lawyer and aliasing is a total pain in the ass, but that's a whole different topic to compilers getting fundamentals wrong because of language lawyering.
Re: Falsehoods programmers believe about undefined behavior
#70Earlier quoted context omitted.
You have to understand that in the modern understanding of UB as applied by compiler writers, the compiler has every right to assume the program never triggers UB. This means that lines which would be UB if a variable had certain values can be used as proof that the variable doesn't have those values, thereby eliminating checks. For example, if a program looks like this: void foo(int* const p) { if (p!=NULL) { bar(p)…
Can you just check, I don't think the line *p=1 will even compile given the definition of p