It's surprising to see so much debate about when or where UB "happens". Unfortunately this article doesn't refer to the best tool to root out UB - UBSan. If you write C or C++, you should have a UBSan+ASan build that is configured to terminate with an error when it encounters violations. You'll save yourself a lot of hair-pulling later. Then you don't have to wonder about the nebulous topics like what "line" the UB "…
Falsehoods programmers believe about undefined behavior
101–110 of 233 posts
Re: Falsehoods programmers believe about undefined behavior
#102Earlier quoted context omitted.
No, it isn't. The line with UB has to be reached in the execution for the execution to be undefined.
The compiler isn't required to know if code is unreachable. For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). Or, here is a better example: for(int i=0; i > n;) { } *p=1; Here the compiler will assume that the loop ter…
Please correct my misunderstanding...
Re: Falsehoods programmers believe about undefined behavior
#103> 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.
This [0] is the linked article for that point, I don’t do systems programming, so I can’t say I understand if this is trivial or not ;) [0]: https://www.ralfj.de/blog/2020/07/15/unused-data.html
Re: Falsehoods programmers believe about undefined behavior
#104Earlier quoted context omitted.
The compiler may make optimization decisions based on the presence of UB so the code only needs to be present. The compiler can't know that an arbitrary part of a function is unreachable if, for instance, that code path is controlled by a parameter or global state since that equates to solving the halting problem. https://blog.llvm.org/2011/05/what-every-c-programmer-should...
I don't think this is correct. If UB is never invoked, the program is conforming and must be translated/executed correctly. DR #109 specifically states that a compiler may not fail to translate a strictly conforming program just because some possible executions could trigger UB: https://www.open-std.org/jtc1/sc22/wg14/docs/rr/dr_109.html Edit: downvoters, please explain your disagreement. I cited a primary document i…
It's just that the generated code may not do exactly what you expect it to do because the presence of undefined behavior allowed the compiler to make assumptions which may surprise you.
edit: It seems that I am incorrect
Re: Falsehoods programmers believe about undefined behavior
#10513. 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…
For example, imagine a C programmer writes a function that adds two `int` values. Hypothetically, with some inputs, the addition may overflow. That would be undefined behavior, so the compiler assumes the function is never called with such inputs, and optimizes accordingly. The programmer knows this, and assures the function is never called with those inputs. Since the only assumption the compiler made was that the function wasn't called with input which would cause the addition to overflow, and the programmer assured that assumption is correct, the function always behaves correctly.
Consider if the same function's inputs were provided at runtime from stdin. The behavior of the whole program is undefined if invalid inputs are given, but if only valid inputs are given, the program must behave correctly.
Re: Falsehoods programmers believe about undefined behavior
#106Earlier quoted context omitted.
No, it isn't. The line with UB has to be reached in the execution for the execution to be undefined.
The compiler isn't required to know if code is unreachable. For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). Or, here is a better example: for(int i=0; i > n;) { } *p=1; Here the compiler will assume that the loop ter…
No it won't. Otherwise all precondition checks would be meaningless. The compiler can only assume that it isn't null when fermats_last_theorem_is_wrong() is true. If the compiler cannot reason about fermats_last_theorem_is_wrong() then it can't just ignore it.
> 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++.
Infinite loops are UB precisely because otherwise the compiler would NOT be able to reason about this. So yes, here the comiler can assume that p is a valid pointer - but only because it can also assume that *p=1 is NOT dead. This falls entirely under the umbrella of behavior not being defined at all after you execute undefined behavior (the infinite loop).
> This remains valid even if you call this function with an n such that *p=1 is unreachable.
Only because the loop itself is undefined behavior in that case.
Re: Falsehoods programmers believe about undefined behavior
#107C needs a mechanism to declare in a source file that certain behaviour must be defined, where that behaviour is undefined in the C standard but the target architecture behaves the defined way. Then, when the source is compiled on the target architecture it works as expected, but when compiled on something else it refuses to compile.
For example, unsigned ints. It'd be great to be able to declare "I define int to be 32 bits and to overflow like a sensible 32-bit int - treat this as defined behaviour, and refuse to compile on a system where this isn't true." The number of platforms where this would fail to compile would be extremely small, and at least they would give a sensible compile error on systems that are weird.
Re: Falsehoods programmers believe about undefined behavior
#108Earlier quoted context omitted.
The compiler isn't required to know if code is unreachable. For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). Or, here is a better example: for(int i=0; i > n;) { } *p=1; Here the compiler will assume that the loop ter…
Presumably (and really don't take my word for this - I'm a Java bod) the p dereference needs to come before the p NULL check for the p NULL check to be ignored. (Otherwise, how can a NULL check protect a dereference.) And therefore, the NULL check would be unreachable as well, and therefore never executed and not relevant. Please correct my misunderstanding...
Re: Falsehoods programmers believe about undefined behavior
#109I have a suggestion - it may be completely off the wall, but hear me out. C needs a mechanism to declare in a source file that certain behaviour must be defined, where that behaviour is undefined in the C standard but the target architecture behaves the defined way. Then, when the source is compiled on the target architecture it works as expected, but when compiled on something else it refuses to compile. For example…
Re: Falsehoods programmers believe about undefined behavior
#110Earlier quoted context omitted.
I don't think this is correct. If UB is never invoked, the program is conforming and must be translated/executed correctly. DR #109 specifically states that a compiler may not fail to translate a strictly conforming program just because some possible executions could trigger UB: https://www.open-std.org/jtc1/sc22/wg14/docs/rr/dr_109.html Edit: downvoters, please explain your disagreement. I cited a primary document i…
The undefined behavior can still affect code generation even though the program gets translated. It's just that the generated code may not do exactly what you expect it to do because the presence of undefined behavior allowed the compiler to make assumptions which may surprise you. edit: It seems that I am incorrect
> 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.
This text specifically allows for the case that a program is strictly conforming even if there is a possible execution that invokes UB. If a program is strictly conforming, it must produce the correct behavior.
I would challenge you to show an example where GCC or Clang will break the correctness of a program on account of UB that is not reached during program execution.
Here is an example where GCC and Clang specifically respects the correctness of a program as long as it does not reach the UB: https://godbolt.org/z/befWah77W