3
votes

A follow-up question to this one

We have the following code:

#include <iostream>

struct A 
{
    static int n;
};

int A::n = 5;

int main() 
{
    A* a; //uninitialized on purpose
    std::cout << a->n; //UB?
}

Is such access an Undefined Behaviour? On one side, no object is needed to access static class members, on the other, operator-> on uninitialized pointer is asking for trouble.

Note: GCC and MSVC compiles this code without any warnings, Clang complains about uninitialized usage. https://godbolt.org/z/Gy5fR2

1
Similar question here although I am rather doubtful about the top answerM.M
I reopened this because the duplicate dealt with null pointers, whereas this question deals with an uninitialized pointer. Since it's not clear whether applying * to a null pointer is UB, the questions are different.Brian Bi
@M.M It's interesting, because the question that was linked here as duplicate originally (stackoverflow.com/questions/3498444/…) has top answer saying "yes, it's UB" and is closed as duplicate with the one you linked, which says "no, it's not".Yksisarvinen
@Yksisarvinen well, I've gone out on a limb and posted an answer to the other questionM.M
@curiousguy I agree with you. It's unclear to me why the committee cannot allocate more time to fixing these issues (after all, it has more membership now than ever before). At the very least, I believe this kind of issue should be fixed before further "improvements" are introduced to the memory/object model which introduce even more issues.Brian Bi

1 Answers

10
votes

The semantics of a->n are that *a is evaluated, but not accessed, since the data member is static. See C++17 [expr.ref]:

... The postfix expression before the dot or arrow is evaluated ... The expression E1->E2 is converted to the equivalent form (*(E1)).E2 ...

There is also a footnote that says:

If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.

In this case, the expression *a is evaluated. Since a is an automatic variable that has not been initialized, [dcl.init]/12 applies:

If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases: [ ... ]

Evaluating *a clearly requires accessing the value of the pointer variable a, which is an indeterminate value, therefore it is UB.