4 ms·
No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.
by suprjami 4y ago
No it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.
- cvchjfjb 4y agoNo, 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 https://blog.regehr.org/archives/213
- leni536 4y agoUB 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.
- tsimionescu 4y agoUB is a property of the source code, or more specifically a property of how source code should be compiled into machine code. It means that there is no constraint on the machine code which will be produced if your source code has certain properties.
- cvchjfjb 4y agoThat is a misconception. "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."
- leni536 4y agoI agree, but this doesn't refute what I wrote. "If any step in a program’s execution has undefined behavior, then the entire execution is without meaning..." Yes. So UB is a property of a given execition, not a static property of the program itself. I don't argue that you can reason about the behavior of any part of the execution, once it evaluates operations with UB.
- gpderetta 4y agoonce and before. If a given execution would eventually lead to UB, then it retroactively it cannot be reasoned about. This time traveling behavior is what is confusing people in thinking that if any execution is UB then all possible executions are UB.
- haberman 4y agoI think this hits the nail on the head. Many people in this thread are confused and think that unreachable UB (either statically or dynamically unreachable) compromises the entire program. This is not true, but your comment helps me better understand how people reached this conclusion. Reachable UB (either provably reached at compile time or dynamically reached at runtime) can retroactively invalidate the correctness of previous statements. But this does not mean that unreachable UB compromises the correctness of well-defined executions.
- gpderetta 4y agoYou are indeed correct. I would add that there are some instances of UB that actually UB at translation time: for example ODR violations and some preprocessor dark corners. At least the latter is getting stamped out.
- leni536 4y agoThe C++ standard calls these "ill-formed, no dioagnosrics required" instead of UB, although it's not always consistent. It is indeed more or less "translation-time UB". The difference is exactly that affected lines don't need to be in the execution path to make all executions undefined, and that the compiler/linker may fail the translation.
- anonymoushn 4y agoA program like int main(int argc, char **argv) { int a = atoi(argv[1]); int b = atoi(argv[2]); return a + b; } contains signed integer overflow in some executions but not others. Can you explain what effect the counterfactual signed integer overflow is allowed to have in executions that do not contain signed integer overflow?
- throwaway294566 4y agoOut-of-order execution isn't the reason for this. The C standard assumes an abstract machine that allows OoOE, of course, but even with strict in-order hardware UB can hit you at any time, even before you'd think it could. That is because the C standard doesn't limit UB to any constraints like "following lines" or "subsequently executed instructions". Independent of the hardware, the compiler is allowed quite a bit of reordering of instructions. The standard just requires that (some) effects of those executions are ordered as written, but that doesn't include UB. So if you have UB in your future path of execution, the compiler might just do whatever _right now_.
- leni536 4y agoIt still has to be executed by the abstract machine for the given set inputs for the whole execution to be undefined. You are right that once the execution is undefined, you can't reason about the behavior. This includes ordering of side effects, or side effects od operations occurring before the line with UB. But uttering UB in dead code making execution UB is utter nonsense. Otherwise any execution of any program that just utters __builtin_unreachable() would be undefined.
- tsimionescu 4y agoThat's sounds plausible, but isn't. First of all, out-of-order execution has nothing to do with unreachable core - it just means that reachable code sometimes gets executed in a different order than the binary shows. It is speculative execution which can lead to unreachable code actually being executed. However, even when processors execute code speculatively, they guarantee that no observable effects of executing that code will happen. So, if you have something like `if false {*NULL=7/0}`, the processor might attempt to execute that line speculatively, but it will revert any change it made, and it will not trap regardless of any other flags.