0
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:

  • Assigning a reference to itself in file scope and block scope.
  • Assigning a pointer to itself in file scope and block scope.
  • Assigning an uninitialized reference to another reference.
  • Assigning an uninitialized pointer to another pointer.
Dan
  • 2,694
  • 1
  • 6
  • 19
  • Does it compile? – tobias Jun 15 '21 at 19:30
  • Yes but could emit warnings as expected. – Dan Jun 15 '21 at 19:31
  • 1
    I get an interesting result for the reference self initialisation at namespace scope - live - https://godbolt.org/z/W84nW5GYY All compilers spot this if the declaration is local. – Richard Critten Jun 15 '21 at 19:34
  • What are you trying to accomplish? Is this just an exercise in obscure quirks of C++? – Dan Mullin Jun 15 '21 at 19:36
  • 1
    @KamilCuk sorry about the typo, it is fixed. – Dan Jun 15 '21 at 19:38
  • 1
    Does this sort of quirk only apply to pointers and references? I don't think `int a = a;` is allowed for example. – tobias Jun 15 '21 at 19:45
  • 2
    @tobias it is allowed. more info on it: https://stackoverflow.com/questions/67979228/in-c-does-initializing-a-global-variable-with-itself-have-ub – Dan Jun 15 '21 at 19:46
  • @Dan The "is allowed" answer applies only to `int i = i;`, not `int a = a;` which is in another context. The difference being the storage duration. There is no difference between int vs pointer in this regard. – eerorika Jun 15 '21 at 19:52

2 Answers2

2
// 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.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • What about the references? Is `int &a = a;` UB. I get a warning for a local variable, but not a global one. – cigien Jun 15 '21 at 19:45
  • `int i = i;` in global scope doesn't seem to have UB according to this: https://stackoverflow.com/questions/67979228/in-c-does-initializing-a-global-variable-with-itself-have-ub#67979333 would the same not apply to global references and pointers? – Dan Jun 15 '21 at 19:54
  • @Dan Same applies to pointers, as per my answer. Note that "doesn't seem to have UB" is somewhat ambiguous. I'm not sure about references. – eerorika Jun 15 '21 at 19:55
  • @Dan I expanded the answer to cover references. – eerorika Jun 15 '21 at 20:31
  • @eerorika I agree on you last edit, references must be initialized but this seems like a loophole. Does `ill-formed` in this case mean UB since its compiling? – Dan Jun 15 '21 at 20:32
  • @Dan ill-formed is essentially the same as UB as far as runtime guarantees are concerned. – eerorika Jun 15 '21 at 20:34
0

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.

kadina
  • 5,042
  • 4
  • 42
  • 83
  • I don't think the question is asking if using the value is UB, but only if the initialization is UB. – cigien Jun 15 '21 at 19:40