Reputation: 2962
Can I pass around references to uninitialized memory, take the address, and then call placement-new or call the destructor on the obtained memory-location. In other words, is the following program legal C++ or does it have undefined-behavior:
#include <string>
#include <iostream>
void ctor (std::string &s)
{
new (&s) std::string ("Hello, world!");
}
void dtor (std::string &s)
{
(&s)->std::string::~string ();
}
int main ()
{
std::string * memory = static_cast<std::string *> (
operator new (sizeof (std::string) * 10));
ctor (memory [0]);
std::cout << memory [0] << '\n';
dtor (memory [0]);
operator delete (memory);
}
It works, of course, and I tried gcc's undefined behavior sanitizer, which didn't produce any errors. But can anyone confirm/refute based on the standard.
Upvotes: 2
Views: 184
Reputation: 206577
dtor (memory [0]);
delete [] memory;
Is definitely undefined behavior.
The lifetime of the object that was constructed in the line
std::string * memory = new std::string [10];
ended when you use the placement new operator.
Hence,
delete [] memory;
is undefined behavior.
Update
The updated lines of code
dtor (memory [0]);
operator delete (reinterpret_cast<void *> (memory));
is well behaved.
The destructor of the object allocated with the placement new operator is called only once.
The memory allocated by the operator new
call gets deallocated by the operator delete
call.
Upvotes: 1
Reputation: 40614
After your edit, there does not seem to be undefined behavior anymore.
However, there's still danger in your code:
Your memory
variable has the type of a pointer to a constructed string, even though there is no string behind that pointer after initialization of the pointer. And the pointer is not nullptr
either. That's dangerous. You are asserting to the compiler that something is a correctly constructed object, which isn't. As such, your compiler won't catch you in the act of using the unconstructed objects erroneously.
I would strongly recommend keeping track of the uninitialized memory with char*
variables, and only use class typed pointers for objects that are already correctly constructed.
Upvotes: 0
Reputation: 275385
The above code double-constructs a string at [0]
, which is a potential resource leak, and double destroys it, which is undefined behaviour.
new string[10]
constructs objects in array. delete[]
destroys the objects. You create a new object on top of another, then destroy it, then destroy it again when you delete[]
.
Nothing else looks wrong; I mean it uses raw allocation which is bad practice in general, and the code is exception unsafe, etc.
Upvotes: 1