3 ms·
You have to look deeper for the OOB array access question. For example, imagine I have code like this: if (a > 1) b++; array[b] = 0; c = a + 10; Un
by caf 11y ago
You have to look deeper for the OOB array access question. For example, imagine I have code like this:
if (a > 1)
b++;
array[b] = 0;
c = a + 10;
Under your suggested semantics, can the compiler use the value loaded from `a` at the point of the if() statement to calculate `a + 10`? Or does it have to emit a reload of `a` after the array access, in case `array[b]` was an OOB access that overwrote `a`?
- Dylan16807 11y agoHow about treating it just like another thread accessing the values? So yes in the general case, no if you put in memory barriers or atomics.
- caf 11y agoRace conditions are generally treated as "you get undefined behavior" for much the same reasons.
- Dylan16807 11y agoI mean race conditions on actual hardware, not the way the standard abandons all hope yet again. Stale reads don't require total chaos.
- userbinator 11y agoI'd say that it doesn't have to read 'a' again because these are separate variables and there's no requirement for 'a' and 'array' to be contiguous, or for that matter 'a' being in memory at all instead of just being in a register. An OOB access could overwrite the memory storing 'a', but I think this case of relying on the ordering and location of objects in memory is just not something any C code would ever have to do.
- lmm 11y agoYou're already allowing undefined behaviour then. Very confusing bugs could result - e.g. the value of 'a' might be different from what it looked like in a debugger, because the array access changed it in memory but the copy in the register hasn't changed.
- nkurz 11y agoI'm not seeing the deeper question, whereas what 'userbinator' said still makes sense to me. The compiler's implementation defined behavior would simply be "if you tell me to write a value to an address, I'll create assembly that tries to write that value to that address". That's all. If this address is outside the allocated range of the array, there is no guarantee that it's safe that write this value, or that it won't break something else. So in your example, no, the compiler is not required to reload 'a'. The compiler is allowed to presume that the array[x] syntax will have no affect on the value of a local variable, whether that variable is stored in a register or on the stack. The compiler is not guaranteeing safety, just best effort.
- caf 11y agoWhen you're saying that the compiler should be allowed to optimise under the assumption that OOB array accesses don't clobber other variables, this means that OOB array accesses can make very weird things happen indeed. For example: if (a > 1) b++; array[b] = 0; if (a > 1) foo(a); We might see foo() called with argument 0 when that's apparently impossible - the OOB write has apparently "reached forward" (it can also "reach backward"). This is why it ends up just being "undefined behaviour" - to do better either you have to somehow exhaustively document all the kinds of weird things that can happen ("it writes to the memory" isn't enough, because of the way that can interact with the optimiser) or you have to unreasonably constrain the optimiser.