Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this std::launder example undefined behavior?

Tags:

c++

This is the part of the example that I don't understand:

struct Y
{
    int z;
};
int main()
{
    alignas(Y) std::byte s[sizeof(Y)];
    Y *q = new (&s) Y{2};
    const int f = reinterpret_cast<Y *>(&s)->z; // Class member access is undefined behavior:
                                                // reinterpret_cast<Y*>(&s) has value "pointer to s"
                                                // and does not point to a Y object
}

And the whole example is at https://en.cppreference.com/w/cpp/utility/launder.

I don't understand why using reinterpret_cast<Y *>(&s)->z is undefined behavior. We have already constructed a Y object at the so-called "pointer to s", and also reinterpreted it to Y*, so why does it still say that "it does not point to a Y object" ?

like image 526
xxhxx Avatar asked Mar 26 '20 15:03

xxhxx


1 Answers

&s is a pointer to a std::byte[sizeof(Y)], not a Y. That means using &s as a Y* is undefined behavior because it violates the aliasing rules. Even though there is a Y living there, the rules of reinterpret_cast (specifically the Type aliasing section) don't allow you to access the object because it can't know there is actually a object there.

std::launder was introduced to explicitly allow you to treat the returned pointer as a valid pointer to the object, instead of a pointer to the storage the object lives in. Essentially, it is an explicit override of the type aliasing rules. You are telling the compiler with it that you know that pointer really does point to a valid object, and if you lied, well then you are back in undefined behavior land.

like image 59
NathanOliver Avatar answered Oct 19 '22 03:10

NathanOliver