Dan
Dan

Reputation: 2886

In C++, does Initializing a reference or pointer with itself cause UB?

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

Answers (2)

eerorika
eerorika

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

kadina
kadina

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

Related Questions