c++c++17undefined-behaviorstdlaunder

std::launder do not work on gcc with -O3 option?


I have code snippet that, I assume, should not produce asserton failure. But with gcc 13.2 with O3 option it fails.

So I think it is Undefined Behaviour here. clang and gcc with O0 works fine. And if I change destructor to some other method - assertion failure dissapears.

#include <cstddef>
#include <new>
#include <cassert>

struct Foo
{
    ~Foo()
    {
        destructed = true;
    }

    bool destructed = false;
};

int main()
{
    alignas(alignof(Foo)) std::byte buffer[sizeof(Foo)];

    Foo* p1 = std::launder(reinterpret_cast<Foo*>(buffer));

    new (p1) Foo();

    assert(p1->destructed == false);

    Foo* p3 = std::launder(reinterpret_cast<Foo*>(buffer));
    p3->~Foo();
    
    //////////// Assertion failure ?????????????????????????
    assert(p3->destructed == true);
    
    return 0;
}

Solution

  • The first call to std::launder has undefined behavior, because when you call it there is no Foo object in its lifetime at the provided address (because Foo isn't an implicit-lifetime type). That's a precondition for std::launder. You may only do the std::launder call after the placement-new.

    And p3->destructed == true has undefined behavior either way, because you ended the lifetime of the Foo object with its destructor call. After that you aren't allowed to access the object anymore.