Reputation: 2886
int &r1 = r1; // r1 0 initialized, `r1` references 0, not UB?
int *p1 = p1; // p1 0 initialized, `p1` is a null ptr, not UB?
int main() {
int &r2 = r2; // reference to intermediate value. has UB ?
int &r3 = r2; // Also has UB ?
int *p2 = p2; // pointer to garbage location. has UB ?
int *p3 = p2; // Also has UB ?
return 0;
}
Evaluating an uninitialized pointer causes undefined behaviour: Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior?
But are the above pointers/references being evaluated?
In this question I wanted to ask about the following cases:
Upvotes: 0
Views: 180
Reputation: 238351
// namespace scope int *p1 = p1; // p1 0 initialized, `p1` is a null ptr, not UB?
Standard is ambiguous regarding this case, but "not UB" could reasonably be argued due to the static initialisation that precedes the dynamic initialisation. On the other hand standard implies that lifetime of the object hasn't started yet.
More details about the ambiguity here: If a global variable is initialized twice (statically, then dynamically), which initialization starts its lifetime?
// block scope int *p2 = p2; // pointer to garbage location. has UB ?
Yes. Unlike in the case of static storage duration, the automatic object lacks the static initialisation stage, and has an indeterminate value before it is initialised. You're using that indeterminate value for the initialisation and the behaviour of the program is unambiguously undefined.
// block scope int *p3 = p2; // Also has UB ?
Behaviour is already undefined in initialisation of p2
. But let's say p2
was an indeterminate value without previous UB:
int *p2;
int *p3 = p2;
The behaviour of this example is undefined as well.
Note that these have little to do with the object being a pointer. This applies to objects of nearly all types.
A reference must be initialised to refer to a valid object or function. Hence all three of these:
// namespace scope int &r1 = r1; // r1 0 initialized, `r1` references 0, not UB? // block scope int &r2 = r2; // reference to intermediate value. has UB ? int &r3 = r2; // Also has UB ?
make the program ill-formed.
I get a warning for a local variable, but not a global one.
I believe that the compiler is non-conforming in its failure to diagnose r1
. Clang does diagnose it, as required. Furthermore, clang's UB-sanitizer detects it at runtime.
Upvotes: 2
Reputation: 5376
In case of global pointers, uninitialized global variables are always initialized to '0'.
Local pointers as you observed pointing to some junk address if not initialized.
References (either local or global) always should be initialized with a variable that means the reference is bound to the variable we are initialized with. But if you are referencing back to the same, then it is undefined behavior. In my case, it is creating core dump when I try to print the value of the reference.
Upvotes: 0