Date: Thu, 13 Nov 2025 23:58:31 +0000
We now have a new compiler up on GodBolt that has
'std::restart_lifetime', and it fixes the vtable pointer after you
relocate a polymorphic object:
https://godbolt.org/z/47jzvj55d
If you look at Line #19 . . . if you change the "#if 1" to "#if 0"
then it crashes -- reason being that the vptr is invalid after the
object is relocated.
And here it is copy-pasted:
#include <cstring> // memcpy
#include <cstdio> // puts
#include <memory> // restart_lifetime
#include <new> // ::new
struct Monkey {
virtual void Hello(void) noexcept { std::puts("Hello"); }
int n;
Monkey(int const arg) noexcept : n(arg) {}
};
int main(int const argc, char **const argv)
{
alignas(Monkey) char unsigned buf1[sizeof(Monkey)];
alignas(Monkey) char unsigned buf2[sizeof(Monkey)];
Monkey *const p1 = ::new(&buf1) Monkey(argc);
std::memcpy( &buf2, &buf1, sizeof buf2 );
#if 1
Monkey *p2 = std::restart_lifetime( p1, (Monkey*)&buf2 );
#else
Monkey *p2 = (Monkey*)&buf2;
#endif
p2->Hello();
p2->~Monkey();
}
'std::restart_lifetime', and it fixes the vtable pointer after you
relocate a polymorphic object:
https://godbolt.org/z/47jzvj55d
If you look at Line #19 . . . if you change the "#if 1" to "#if 0"
then it crashes -- reason being that the vptr is invalid after the
object is relocated.
And here it is copy-pasted:
#include <cstring> // memcpy
#include <cstdio> // puts
#include <memory> // restart_lifetime
#include <new> // ::new
struct Monkey {
virtual void Hello(void) noexcept { std::puts("Hello"); }
int n;
Monkey(int const arg) noexcept : n(arg) {}
};
int main(int const argc, char **const argv)
{
alignas(Monkey) char unsigned buf1[sizeof(Monkey)];
alignas(Monkey) char unsigned buf2[sizeof(Monkey)];
Monkey *const p1 = ::new(&buf1) Monkey(argc);
std::memcpy( &buf2, &buf1, sizeof buf2 );
#if 1
Monkey *p2 = std::restart_lifetime( p1, (Monkey*)&buf2 );
#else
Monkey *p2 = (Monkey*)&buf2;
#endif
p2->Hello();
p2->~Monkey();
}
Received on 2025-11-13 23:58:42
