Calling destructors on new placement buffer? - c++

So i have this class
class Obj{ //simple class with constructor + destructor
public:
Obj(){cout<<"Obj1 has been created"<<endl;}
~Obj(){cout<<"Obj1 has been destroyed"<<endl;}
};
Obj * buffer[10]; //buffer
int main(int argc, char *argv[])
{
Obj * c = new(&buffer[0]) Obj;
delete &buffer[0];
system("PAUSE");
return EXIT_SUCCESS;
}
Is this method of using placement "new" a valid one? because when i tried deleting the address, the destructor wasn't called.
but if i use this line of code, the destructor gets called
Obj * c = new(&buffer[0]) Obj;
delete c;
Can someone tell me what's happening? do i really have to delete the pointer to call out the destructor?

The use of placement new in your example as well as the attempt to destroy it are both invalid:
The array buffer contains pointers to Obj. There is no guarantee that a pointer yields sufficient space for an object or that a pointer is properly aligned to hold an object of an object.
To destroy an object constructed with placement new you'll need an explicit destructor call which looks something like ptr->~Obj().
A proper use of placement could be something like this:
Obj* objects[10];
char* buffers[10];
// ...
buffers[1] = new char[sizeof(Obj)];
objects[1] = new(buffers[1]) Obj();
// ...
objects[1]->~Obj();
delete[] buffers[1];
(obviously, in real code you'd protect the different buffers and objects by suitable RAII classes to avoid resource leaks).

With placement new you must call the destructor directly.
buffer[0].~Obj();
// or
c->~Obj();
You must NOT call delete on the object as this will try and release the memory. Since the memory was not allocated with new this is undefined behavior.
// delete &buffer[0]; Don't do this.

Related

Do i need to delete a object that was constructed with new and placement

class Foo{
//some member
public:
int bar;
}
int main(){
char* buffer = new char[100];
Foo* f = new(buffer)Foo();
//do i have to
delete f;
//or is
delete[] buffer;
//enough
}
Sure i have to delete it if the delete of Foo has some major effect on the system but lets say it is a simple storage object which i place which is compleatly inside of the buffer and has no deconstructor which does delete some other things.
Do i have to delete a object which where places with the new inside
of a buffer or is it enough to delete the buffer?
If i have to call delete on every object inside of the buffer, why do
i have todo this?
I read: what-uses-are-there-for-placement-new and he also says
You should not deallocate every object that is using the memory buffer. Instead you should delete[] only the original buffer.
The correct way to destroy that object is with an explicit destructor call:
f-> ~Foo();
Usually placement new is used with memory on the stack. In this case, it's heap allocation, so you do need to free the buffer using the form of delete that matches the new.
delete[] buffer;

How to renew an object in C++

I have the following code:
vector<SomeClass> objs;
SomeClass obj; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue()){
use(&obj);
obj = new SomeClass(); // create a new obj with an existing name
objs.pushback(obj)
}
in this code new SomeClass(); is in java OOP form - and is not a c++ code. what code should be used instead of obj = new SomeClass();?
The answer is:
obj = SomeClass();
new SomeClass() will return pointer to SomeClass object. You cannot assign it to varible obj, which type is SomeClass, not SomeClass*.
EDIT: If I remember well, SomeClass obj(); should also work.
I think what you wanted is something like that:
vector<SomeClass *> objs;
SomeClass* obj = new SomeClass; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue())
{
use(&obj);
obj = new SomeClass; // create a new obj with an existing name
objs.push_back(obj)
}
Your understanding of the language is somewhat off. Here is your code as annotated:
vector<SomeClass> objs;
SomeClass obj; // create a new obj with a new name
objs.push_back(obj);
while (someConditionIsTrue()){
use(&obj);
obj = new SomeClass(); // create a new obj with an existing name
objs.pushback(obj)
}
Here is what ACTUALLY happens
// create an object called "objs" which is a std::vector header, on the stack.
vector<SomeClass> objs;
// create an instace of "SomeClass" on the stack, call it obj.
SomeClass obj;
// allocate storage in the heap for some number of SomeClass instances to
// act as the storage for "objs", and assign them to it's "m_data" member.
// default construct the first one,
// then call it's copy constructor with the stack instance of "Obj" to
// copy the values/data into the first entry of the heap allocation of objs.
objs.push_back(obj);
while (someConditionIsTrue()){
// pass a pointer to the stack-allocated instance of obj.
use(&obj);
// create a new instance of "SomeClass" on the heap,
// default/zero construct it,
// return the pointer to this heap allocation and pass it
// to obj.operator=(const SomeClass*) to copy the data into
// the stack space allocated for "obj".
obj = new SomeClass(); // create a new obj with an existing name
// leak the pointer to the previous heap allocation by not storing it.
// increase the size of the heap allocation backing objs and then
// default construct the first SomeClass instance in the new space,
// then copy our freshly copy-initialized stack instance back into it.
objs.pushback(obj)
}
You could write this code numerous other ways, but it seems like the most sensible would be.
std::vector<SomeClass> objs;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1); // grow me a new element.
use(&objs.back());
}
Or make "use" take a reference.
void use(SomeClass& obj);
//...
use(objs.back());
If you really want a local object to try the entry.
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
// the compiler will either optimize this out entirely,
// or use a pointer under the hood.
SomeClass& obj = objs.back();
use(&obj); // take the address of the object obj references.
}
Also, be aware that "resize()" can get expensive. You might want to do this upfront:
objs.reserve(1024); // or something you know is likely to cover most use cases.
If you really, really have to use a pointer.
SomeClass* obj = nullptr;
while (someConditionIsTrue()) {
objs.resize(objs.size() + 1);
obj = &objs.back();
use(obj);
}
Instead of "objs.resize()" you may be able to use placement-new with a ctor:
objs.emplace_back(SomeClass());
Others have suggested that you use
obj = Someclass();
But note that this is copying a default-constructed stack copy of the object.
{
SomeClass tempObj;
obj.operator=(std::move(tempObj));
}
I don't think that's what you actually want to do. It's more expensive than just having a stack-local copy like this:
while (someCondition()) {
SomeClass stackCopy;
...
}
the compiler is smart enough not to give up the stack space each loop. What it will do is a thing called "Placement new" to re-invoke the constructor on the same object:
SomeClass obj;
while (someCondition()) {
new (&obj) SomeClass(); // Call SomeClass() ctor on the memory at &obj
...
}
But - this is basically how the compiler achieved my previous code sample.

c++ local variable memory management

I have the following code:
void someFunction() {
.......
myClass obj= *(new myClass());
........
delete &obj;
}
I get a runtime error saying invalid pointer.
The code runs fine without the "delete" line.
I know that I need to re-claim memory allocated dynamically by new operator. But I don't know what is going on in this case and how or even do I need to free the memory?
Thanks
If your intent is for the instance to only exist within the scope of this function, then you don't need to use dynamic allocation...
void someFunction() {
.......
myClass obj;
........
}
... in which case the obj constructor is called when it is declared at myClass obj and the destructor is called when the function returns. Otherwise, if it must be dynamic, then this...
void someFunction() {
.......
myClass* obj = new myClass();
........
delete obj;
}
... in which case the constructor is called when you call new myClass() and the destructor is called when you call delete obj -- but, in this case, you need to declare obj to be a pointer to a myClass object so that there's a place to store the return value from the new.
In your example I don't think you can re-claim the memory.
obj is a copy of the anonymous class you create with *(new myClass()). "obj" is allocated on the stack... it is not allocated on the heap (which is where new allocates from).
When you try to delete &obj you are trying to delete the stack memory for the copy that you created.
Try something like
myClass *obj = new myClass(); // memory is allocated from the heap and a pointer returned
myClass copyOfObj = *obj; // memory is allocated on the stack. a *shallow* copy of obj is made
delete obj.
myClass obj= *(new myClass());
That line:
Creates an instance of myClass with automatic storage duration.
Dynamically allocates an instance of myClass.
Dereferences the returned pointer and copies the object to obj. The pointer to the dynamically allocated object is discarded, resulting in a memory leak.
Call delete on a pointer to a local variable with automatic storage duration, which results in undefined behavior. This object was not allocated with new or any variant of new.
Your code should be:
myClass *p = new myClass();
// use p
delete p;
You probably don't need dynamic memory allocation at all, so...
myClass obj; // that's it!
Next, read up on smart pointers.
std::unique_ptr<myClass> p(new myClass());
// no delete! unique_ptr handles it for you when it goes
// out of scope and has the benefit of being exception safe.
Your obj variable has to hold a reference to the dereferenced pointer, so that it later can (rather oddly) delete it:
myClass& obj;
// ^
But you need not define it this way, you can define a pointer to the memory instead:
myClass* obj = new myClass();
and delete it this way:
delete obj;
Or, better yet, you can use memory management tools like std::unique_ptr:
std::unique_ptr<myClass> obj(new myClass);
But there really is no use here for dynamic memory as far as I can see, just intantiate it as a normal variable:
myClass obj;
myClass obj= *(new myClass());
This first creates a myClass object with automatic storage duration named obj. This object is initialised by the expression *(new myClass()). This expression dynamically allocates a myClass object and then dereferences the pointer to that object. So what you end up doing here, is dynamically allocating an object and then copying that into obj.
You've now lost track of the dynamically allocated object. That's not good. Doing delete &obj; will only take the address of the automatic object and attempt to destroy that, but you must only use delete with dynamically allocated objects.
You could change obj to be a reference and it would work:
myClass& obj = *(new myClass());
This makes sure the dynamically allocated object isn't copied. However, this isn't a good idea. It masks the fact that obj refers to an object that must be deleted. Instead, you're better off storing the pointer itself:
myClass* obj = new myClass();
// ...
delete obj;
Or even better, use a smart pointer like std::unique_ptr<myClass>.
Or even betterer, don't even both dynamically allocating it. Just use an automatic object:
myClass obj;
// No need to allocate or delete anything

Possible mem leak?

I'm new to the concept so don't be hard on me.
why doesn't this code produce a destructor call ?
The names of the classes are self-explanatory.
The SString will print a message in ~SString().
It only prints one destructor message.
int main(int argc, TCHAR* argv[])
{
smart_ptr<SString> smt(new SString("not lost"));
new smart_ptr<SString>(new SString("but lost"));
return 0;
}
Is this a memory leak?
The impl. for smart_ptr is from here
edited:
//copy ctor
smart_ptr(const smart_ptr<T>& ptrCopy)
{
m_AutoPtr = new T(ptrCopy.get());
}
//overloading = operator
smart_ptr<T>& operator=(smart_ptr<T>& ptrCopy)
{
if(m_AutoPtr)
delete m_AutoPtr;
m_AutoPtr = new T(*ptrCopy.get());
return *this;
}
By new smart_ptr<SString>(new SString("but lost")); you are creating a new, dynamically allocated smart pointer. You don't store the result of the allocation (a pointer to a shared_ptr to a SString) anywhere, it's dangling... since you don't store the result, you also can not call delete for it - therefore it's destructor won't be called, and in turn also the SString destructor of the contained object won't be called!
If you try
smart_ptr<SString> *p = new smart_ptr<SString>(new SString("but lost"));
delete p;
instead, you will see the destructor called also for this case.
However, that's no sensible use of a smart_ptr. smart_ptr were created so that you don't need to call delete manually; therefore, don't use them that way; use them as in your first statement!
The point of a smart pointer is that you're supposed to have only automatic smart pointer objects:
{
smart_ptr<Foo> p(new Foo);
}
// bye bye Foo
Your second line, however, creates a dynamic smart pointer, whose life never ends! Thus it never gets a chance to destroy the object it's in charge of.
You would have to delete the smart pointer itself manually, so that it can in turn clean up the object:
auto sp = new smart_ptr<Foo>(new Foo);
// ^^^^^^^
// ^^^^^^^^^^^^^^ +------< dynamic Foo, handled by the SP
// |
// +---------------< dynamic smart pointer, handled by YOU
delete sp;
Yes, the smart point itself is leaked. (And anything it holds a reference to).
I cannot think of a good reason to new a smart pointer...
Yes, it is a memory leak, you're leaking the second smart pointer and its contents.
The reason is that the first smart pointer is created on the stack, so its life-time is scoped to the block it is declared in, after that it will be automatically destroyed.
The second one is created on the heap, which means it will live until you destroy it with delete at which point its destructor will be called (and with that the destructor of the SString it is holding).

How do I delete memory after manually invoking destructor?

I was reading this question Does calling a destructor explicitly destroy an object completely? where this situation comes up in code.
Object* aWidget = new Widget(); //allocate and construct
aWidget->~Object(); //destroy and DON'T deallocate
From the answers, I undrestand that the memory region is in fact not deallocated in this situation. My question is (more out of curiosity than anything):
How can I delete the memory pointed to by aWidget after the two lines of code above have executed? I would assume calling delete aWidget; would fail because it would try to run the destructor on an already-destructed object. Could you call free(aWidget) or something like that instead to just target the memory?
free would, factually speaking, be my best guess. However I don't think you can do anything without invoking UB. How did you arrive at a requirement to invoke the destructor like that?
Calling free on an object allocated with new is undefined behavior.
I suggest you keep it simple, and call delete.
However, if you want to do this, you can, in some cases, call delete even if you previously called the destructor explicitly. If you call it explicitly, you can view it as a function. The memory isn't freed, so I'm guessing setting member pointers to NULL after you destroy them would be enough to prevent you from running into any trouble. (because calling delete on a NULL pointer is a no-op).
For example, the following should be ok:
class A
{
public:
int * x;
A()
{
x = new int[10];
}
~A()
{
delete[] x;
x = NULL;
}
};
int main()
{
A* a = new A;
a->~A();
delete a;
return 0;
}