Is it not UB to move-construct an object via placement new?
Let's say I have this code:
class Foo {
public:
Foo() { foo_ = new int; }
~Foo() { delete foo_; }
Foo(Foo &&f) {
foo_ = std::swap(f.foo_, foo_);
}
private:
int* foo_;
}
void bar() {
void* pMem = malloc(sizeof(Foo));
Foo f1;
// move-construct with placement new:
new((Foo*)pMem) Foo(std::move(f1)); // f2 in *pMem
// now f1 will contain a pointer foo_ of undefined value
// when exiting scope f1.~Foo(){} will exhibit UB trying to delete it
}
If it's not obvious, f1's member foo_ will have an undefined value after constructing the second foo by placement new and move construction (this undefined value comes from the uninitialized Foo f2's foo_ inside its move-constructor because the values are swapped)
Thus, when exiting the scope of bar(), f1's destructor will try to delete an invalid (uninitialized) pointer.
This has nothing to do with placement new. This code would have the exact same problem:
void bar() {
Foo f1;
Foo f2(std::move(f1));
}
Every constructed object will get destructed eventually, so it doesn't matter if you use placement-new or not, your move-constructor messes up by leaving the moved-from object in a invalid state. Moving from an object doesn't mean it won't get destructed. It will. You have to let a valid object behind when you move from it.
Foo(Foo &&f) : foo_(nullptr) {
std::swap(f.foo_, foo_);
}
will fix the bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With