4 ms·
Can someone with more knowledge chip in? If I define void bar(int* const p, int n) { for (int i=0; i<n; ++i) { int m = *p // other code (with
by yccs27 4y ago
Can someone with more knowledge chip in? If I define
void bar(int* const p, int n) {
for (int i=0; i<n; ++i) {
int m = *p
// other code (without UB)
}
}
it might get optimized via loop-invariant code motion to
void bar(int* const p, int n) {
int m = *p
for (int i=0; i<n; ++i) {
// other code (without UB)
}
}
so it could still be UB when called with p=NULL and n=0, right?
Edit: Oops, in the previous version I used a write instead of a read on *p, making the optimization invalid.
- caf 4y agoNo, that transformation is straight-up buggy unless the compiler can also prove that n > 0 (ie by inlining the bar() function into a context where n is always positive). If you had *p == 0 before calling bar(p, 0) then *p had better not be 1 after!
- MushyQuadrant 4y agoThe first form has no undefined behavior. Since p may be NULL, in general the compiler is not allowed to make that transformation unless it can prove bar never gets called with p=NULL and n=0 (which it probably can't). If the compiler has some special knowledge of the target architecture which makes the second form behave as if the first form was executed (such as if NULL is a valid address on the target architecture), it may make the transformation, but that still wouldn't cause undefined behavior, because it must behave as if it had the first form.
- yccs27 4y agoThank you for clarifying! It's definitely relieving, after reading the post, to know that there is some limit for undefined behavior.