I'm creating some Objects inside a loop and add it to a listwith:
list<MyObject> myList;
MyObject* ob = new MyObject();
ob.setAttribute("whatever");
myList.push_back(*ob);
After the loop finishes, I'm using the list several times.
I've started now a Leak Detector and saw, that I've to delete all the MyObject objects.
How I delete them properly (In the destructor?). Should I use a iterator? But how I get the real object - and not the iterator pointer?
Thanks a lot.
There's absolutely no reason for dynamic allocation here, since the list stores objects by value. All you're doing is copying and discarding a dynamic object; it's leaked immediately since you don't keep a pointer to it anywhere. Just push objects directly, copying a temporary or automatic variable if necessary:
list<MyObject> myList;
MyObject ob;
ob.setAttribute("whatever");
myList.push_back(ob);
If you did need to store pointers, perhaps for polymorphism, then you'd use smart pointers to avoid leaks:
list<std::unique_ptr<MyBase>> myList;
std::unique_ptr<MyObject> ob(new MyObject);
ob->setAttribute("whatever");
myList.push_back(ob);
If you really want to juggle raw pointers for some reason, then yes, you will have to delete them yourself. You really shouldn't try to do that.
You don't need to delete them, they're copied when added into the list by push_back(). But, you need to delete ob after you used it. Such as:
list<MyObject> myList;
MyObject* ob = new MyObject();
ob.setAttribute("whatever");
myList.push_back(*ob);
delete ob;
Basically, you don't need to use pointer here, you can just declare ob in stack to avoiding the manual memory management:
list<MyObject> myList;
MyObject ob;
ob.setAttribute("whatever");
myList.push_back(ob);
And, according to your program's requirment, you can use some kind of smart point to avoiding such manual memory management, such as:
list<std::shared_ptr<MyObject>> myList;
myList.push_back(new MyObject);
...
// don't need to delete them manually
Related
I'm new to computer science and I want to know if an object is being deleted if I heap allocate it and then for e. put it in a vector of pointer and then delete the vector. Will the heap object be gone? Here is an example of what I mean.
int main()
{
Type* someHeapObject = new Type();
vector<Type*> someVector(0);
someVector.push_back(someHeapObject);
}
So here's the main part: Can I delete the heap object with delete someVector[0], and then I DON'T have to delete it anymore like this: delete someHeapObject
There are two things that you have to take care of:
Mistake 1
In delete [] someVector you're using the delete [] form when you should be using the delete form because you used the new form and not the new[] form for allocating memory dynamically. That is, delete [] someVector is undefined behavior.
Mistake 2
The second thing that you must take care of is that you should not use two or more consecutive delete's on the same pointer.
Now, when you wrote:
someVector.push_back(someHeapObject);
a copy of the pointer someHeapObject is added to the vector someVector. This means that now there are 2 pointers pointing to the same dynamically allocated memory. One pointer is the someHeapObject and the second is the one inside the vector.
And as i said, now you should only use delete on only one of the pointers. For example you can write:
delete someHeapOjbect; //now the memory has been freed
//YOU CAN'T USE delete someVector[0] anymore
Or you can write:
delete someVector[0]; //now te memory has been freed
//YOU CAN'T USE delete someHeapObject[0] anymore
Note that better option would be to use smart pointers instead explicitly doing memory management using new and delete.
Suppose I have a function or class that maintains some pointers to other data objects, like so:
class MyObject {
...
AnotherObject* o1, *o2;
SomeObject* s1, *s2;
...
}
int main() {
...
MyObject mo1 = new MyObject();
... // do stuff with mo1
delete mo1;
}
Suppose they are assigned valid pointer values from elsewhere during/after initialization.
When I destroy the MyObject object after assigning those pointers inside, can a memory leak result if I do not null the pointers during destruction like so?:
MyObject::~MyObject() {
o1 = nullptr;
o2 = nullptr;
...
}
Thanks.
No it won't cause a memory leak. Note however that this:
MyObject mo1 = new MyObject();
// do stuff with mo1
delete mo1;
will result in a memory leak if do stuff with mo1 throws an exception (which could be the case if it comprises references to nullptr). Therefore it's advisable not to use naked pointers like you do but smart pointers instead - this way RAII guarantees that your pointer will be deleted.
It sounds like you come from a Java background, where setting pointers to null is necessary to allow the garbage collector to reclaim other objects. If so, the answer is simple: no, that's not how it works in C++. Setting a pointer to null has no bearing whatsoever on memory usage, and there is no garbage collector anyway that could reclaim any memory.
Instead you are supposed to consider ownership. Most objects have one specific owner; once that owner is deleted, so are its owned objects. This is most conveniently modelled using unique_ptr instead of raw pointers. For objects that have more complex ownership, there is shared_ptr and weak_ptr.
Once again, there is no garbage collector, so any time you use new to create an object, somehow, somewhere there must be a corresponding delete. The easiest way to ensure such deletes are not forgotten is to use unique_ptr.
Also be wary of using new too often. Your mo1 object can be allocated on the stack without any problem: it's lifetime is limited to one function (main), so why not use simply allocate it as MyObject mo1; - that's enough, no need to new or delete anything.
No it would not. Memory leak happens because of a non-deleted memory which was allocated using new. Nulling a pointer is just a way to check it later if it was deleted or not and it has nothing to do with memory leak.
On the other hand, dealing with memory manually is not a the best way to achieve what you want. Smart pointers are exist (std::shared_ptr, std::unique_ptr...). You should have a look on them.
This question already has answers here:
Does std::list::remove method call destructor of each removed element?
(6 answers)
Closed 9 years ago.
I have a class that contains pointers, the class inherits nothing
class MyClass
{
public:
MyClass();
~MyClass();
private:
//i have pointers here
};
MyClass::~MyClass()
{
print("destroyed..");
}
Now i have to use this class as a pointer in vector like this:
vector<MyClass*> classes;
Push some classes in here but when i remove an element:
classes.remove(index);
The destructor doesn't get called,and i think that I have a memory leak.
So how do i make it call the destructor
A vector of pointers does nothing to delete the pointers when they get removed or cleared from it. The vector cannot know if the pointers are dynamically allocated or not. It is not it's job to call delete.
It is up to you to call delete on the pointers, if and when it is necessary. There are not enough details in your question to determine whether it is necessary at all (you haven't shown how the objects pointed to are allocated). But since you claim there is a memory leak, this could indicate that they are dynamically allocated. The immediate solution is to call delete:
delete *it;
classes.erase(it); // vector has no remove member function
A safer solution is to store unique ownership smart pointers, such as std::unique_ptr<MyClass>. The standard library also provides smart pointers for shared and weak ownership. See Smart Pointers.
All the above is assuming that you do actually need to store a pointer. In general, it is safer and clearer to store values:
std::vector<MyClass> classes; // but don't call it "classes". A vector stores objects.
That's one of the reasons why you should avoid using std::vector<MyClass*> at first place. There's an ugly memory management connected with it and it won't stay as easy as classes.remove(index);
Basically, for every new a delete must be called and for every new[] a delete[] must be called, no matter whether you use this pointer as a local variable or you put it into the vector:
vector<MyClass*> vec;
vec.push_back(new MyClass()); // <-- object has been created
...
delete classes[index]; // <-- object shall be destructed
// the delete call will automatically invoke the destructor if needed
...
// now you can remove the dangling pointer from the vector
Just note that once the object has been destructed, any (old) reference to this object is invalid and trying to access this object using such reference (dangling pointer) will yield undefined behavior.
Firstly, std::vector has no remove, you probably mean erase.
Secondly, you need to manually call delete on whatever you're removing:
vector<MyClass*> classes;
auto iter = <iterator to index to remove>;
delete *iter;;
classes.erase(iter);
Or, to avoid all this pain, use a std::unique_ptr<MyClass>.
It is unclear who is responsible for managing the lifetime of the objects pointed by the pointers inside classes. Have you pushed newed pointers into it, or have you pushed the addresses of automatic storage objects?
If you have done the former, then you must manually delete the pointer before removing it. Else, if you have done the latter, then you could just leave it as is, just leaving the pointed-to objects destroy themselves as they leave their respective scopes. If you have mixed newed and non-newed pointers, whose possibility isn't that remote as you would think, then you're definitely damned, undefined behavior making demons fly out of your nose.
These kinds of situations involving pointers are very ambiguous, and it is generally recommended not to use pointers at all, and make the std::vector store plain objects, which makes your object lifetime management much simpler and the making the declaration just speak for itself.
vector<MyClass> classes; // Do this instead
You have to manually delete your pointers before your application exit or after your class object is removed from vector.
// Delete all
vector<MyClass*>::iterator it = classes.begin();
while (it != classes.end()) {
delete *it;
it = classes.erase(it);
}
Tip: Never add stack constructed pointers like following:
MyClass m;
classes.push_back(&m);
Edit: As suggested by other member the better solution is:
MyClass m(/* ... */);
vector<MyClass> classes;
classes.push_back(m);
However please note, you have to properly implement the copy constructor especially if your class has pointer data members that were created with new.
Make a temp pointer to hole MyClass* pointer before you remove it from your vector.
vector<MyClass*> classes;
//push some classes in here but
//when i remove an element
MyClass* temp = classes[index];
classes.remove(index);
// call delete temp; if you want to call the destructor thus avoid memory leak.
delete temp;
To avoid memory leak, remember never to loose control of heap object, always keep a a pointer or reference to it before object release.
It seems that you want your vector to be manager of your items.
Take a look at boost::ptr_vector class
its basically a wrapper around std::vector class.
You declare that this vector is the "holder" of these pointers, and if you remove them from this containers you want them to be deleted.
#include <boost/ptr_container/ptr_vector.hpp>
...
boost::ptr_vector<MyClass> myClassContainer;
myClassContainer.push_back(new MyClass());
myClassContainer.clear(); // will call delete on every stored object!
I have had a good look at some other questions on this topic and none of them (to my knowledge) address how to correctly erase items from a stl list of objects which contain dynamicically assigned memory vs. a stl list of objects that don't contain dynamically assigned memory.
I want to use a list of objects. Take this object for example (which contains no dynamically assigned memory):
class MyPoint {
public:
MyPoint(int _x,int _y)
{
x = _x;
y = _y;
}
private:
int x;
int y;
};
So I might create a list of objects (not pointers to them), add things to it and then erase an element:
list<MyPoint> myList;
myList.push_back(MyPoint(3,4));
myList.push_back(MyPoint(1,2));
myList.push_back(MyPoint(8,8));
myList.push_back(MyPoint(-1,2));
list<MyPoint>::iterator it;
it = myList.begin();
advance(it,2);
myList.erase(it);
My list now contains:
(3, 4)
(1, 2)
(-1, 2)
QUESTION 1a: do I need to do anything else to the erased object or will the memory be taken care of?
QUESTION 1b: if the program ends, do I need to do something with the remaining objects in the list? Do I need to delete them all and deal with their memory somehow?
Ok, now consider an alternative version of the class that allowed a point in N-dimensional space. I.e., I could dynamically assign an array of length N to hold the N points inside the class (I have spared you the implementation as that is not in question here). The destructor of the class would then delete the dynamically assigned array using 'delete'.
class MyDynamicPoint {
public:
MyDynamicPoint(int N)
{
points = new int[N];
}
~MyDynamicPoint()
{
delete points;
points = NULL;
}
private:
int *points;
};
I might now create a list of pointers to the objects, instead of the objects themselves:
list<MyDynamicPoint*> myList;
myList.push_back(new MyDynamicPoint(8));
myList.push_back(new MyDynamicPoint(10));
myList.push_back(new MyDynamicPoint(2));
myList.push_back(new MyDynamicPoint(50));
list<MyDynamicPoint*>::iterator it;
it = myList.begin();
advance(it,2);
myList.erase(it);
QUESTION 2a - Is the above correct? I.e. Because this new version of the class would contain some dynamically assigned memory, does this mean I have to create a list of pointers to objects, not the objects themselves?
QUESTION 2b - Given that I have just erased the pointer from the list, where do I call delete to deal with the fact there is now dynamic memory to be deleted in the objects? Or does the erase method of stl list call the destructor of the object, taking care of it?
Many thanks in advance for any help,
Best,
Adam
When you have a class with data members that have automatic storage duration (i.e. their lifetime is tied to the instance of this class) like this:
class MyPoint {
private:
int x;
int y;
};
and you will use list<MyPoint> myList;, then this instance of std::list is also an object with automatic storage duration, that will be cleaned up automatically and by the time the container is destructed, so are the elements it holds. Everything is taken care of.
But the latter version is not very lucky choice... not only that you have a container holding pointers, you even decided to create a data member of class Point that will be allocated dynamically. At first note that everything that has been allocated by calling new should be freed by calling delete and everything allocating by calling new[] should be freed by calling delete[].
In this situation, you are allocating the memory when the object is constructed and cleaning it up when the object is destructed:
MyDynamicPoint(int N)
{
points = new int[N];
}
~MyDynamicPoint()
{
delete[] points;
points = NULL;
}
private:
int *points;
You would achieve the same by using some std::vector or std::array instead of the C-style array and you wouldn't have to take care of the memory management on your own:
MyDynamicPoint(int N) : points(std::vector<int>(N, 0)) { }
private:
std::vector<int> points;
the std::vector object will take care of memory management for you.
And last thing: when you dynamically allocate an element and store it into the container:
myList.push_back(new MyDynamicPoint(8));
you need to free this memory on your own, erasing the pointer from the list is not enough:
list<MyDynamicPoint*>::iterator it;
...
delete *it;
myList.erase(it);
So whatever you want to achieve, always prefer objects with automatic storage duration if the situation allows it. There's nothing worse than being forced to taking care of memory management manually and dealing with unpleasant problems such as memory leaks later.
QUESTION 1a: do I need to do anything else to the erased object or will the memory be taken care of?
You don't need to do anything.
QUESTION 1b: if the program ends, do I need to do something with the remaining objects in the list? Do I need to delete them all and deal with their memory somehow?
You don't need to do anything.
QUESTION 2a - Is the above correct?
The code is not correct. You're violating The Rule of Three. In particular, the automatically-generated MyDynamicPoint's copy constructor and assignment operator will make a bitwise copy of the points pointer. If you copy an instance of MyDynamicPoint, you'll end up with two object sharing the same points pointer:
When one of the objects goes of scope, the other becomes unusable.
When the second object goes out of scope, its destructor will attempt to free memory that's already been freed. This is undefined behaviour.
I.e. Because this new version of the class would contain some dynamically assigned memory, does this mean I have to create a list of pointers to objects, not the objects themselves?
No, it does not mean that. In fact, you should probably continue to store objects by value. However, you do need to fix the rule of three.
QUESTION 2b - Given that I have just erased the pointer from the list, where do I call delete to deal with the fact there is now dynamic memory to be deleted in the objects? Or does the erase method of stl list call the destructor of the object, taking care of it?
Since you have a list of raw pointers, the destructors will not be called automatically. The easiest way to fix that is to either store objects by value, or use std::unique_ptr or std::shared_ptr instead of raw pointers.
To question 1, there is nothing you need to do. As you store the objects by value the compiler and the library will handle everything.
However, when you store pointer as in the second case, you need to delete those pointers that you have allocated with new, or you will have a memory leak.
And you have to delete the pointers before doing the erasing, as that can invalidate the iterator:
delete *it;
myList.erase(it);
I think following should work
MyPoint* ptr = myList.back();
delete ptr;
myList.pop_back();
OR
MyPoint* ptr = myList.back();
delete ptr;
myList.erase(ptr);
I want to store 10 Obj object in objList, but i don't know when is appropriate use delete in this case. If i use delete Obj; in the line where i note in below code, will the Obj still be stored in objList?
struct Obj {
int u;
int v;
};
vector<Obj> objList;
int main() {
for(int i = 0; i < 10; i++) {
Obj *obj = new Obj();
obj->u = i;
obj->v = i + 1;
objList.push_back(*obj);
// Should i use "delete Obj;" here?
}
}
Any object you create on the heap with new needs to be cleared up by delete. In your code, you are actually storing a copy in your collection.
objList.push_back(*Obj);
What this line is doing step by step is:
Indirecting a pointer to the underlying heap memory Obj occupies (returning the object Obj)
Calling the copy constructor to create a temporary copy
Storing the temporary copy in the collection
You do not need to create this initial Obj on the heap, a stack allocated local will suffice as #Luchian Grigore has pointed out.
Obj obj;
objList.push_back(obj);
You do not need to call delete on the copy in the collection, the STL collection will handle this memory itself when you remove the element, but you still will need to delete the original heap allocated object.
It would be better if you stored your objects by std::shared_ptr. That way delete would be called when all references to the Obj were removed.
std::vector< std::shared_ptr< Obj > > vec;
vec.push_back( std::make_shared( new Obj() ) );
Yes, you should.
There should be a corresponding delete for every new in your program.
But your program doesn't need dynamic allocation:
Obj obj;
obj.u = i;
obj.v = i + 1;
objList.push_back(obj);
Also, your syntax was wrong - objList.push_back(*Obj); // should be *obj, not *Obj
Think about what happens:
In your loop you create a new instance of Obj and assign some values to it. This instance is created on your heap - thus you have to free it afterwards. When you add the instance to the vector you implicitely create a copy of it - because you have a vector of objects, not of pointers. Thus the vector keeps its own copy of Obj. You are safe to delete your Obj instance.
BTW:
you could even reuse the object instance and create and free it outside of your loop
it's not necessary to allocate the Obj instance on the heap
Obj x; x.u =i; x.v = i+1; objList.push_back(x);
would also do
You should read some articles about smart pointers and smart pointer containers. Eg. boost::scoped_ptr, boost::shared_ptr, std::auto_ptr. Using these paradigms there's usually no need to call delete by yourself.
You wanna use the heap, so I suggest changing your vector declaration to vector of pointers, something like this.
vector<Obj *>objList;
Why? Because if it is a vector of Obj's, then the things you're storing are actually copies of the value Obj of the pointers you created. objList's items and the obj pointers you create are totally separated and unrelated!
So when you,
delete obj
The things on objList are totally completely unaffected in any ways.
Moreover, vector<Obj> (no asterisk), stores its item as Obj and they are on the stack, they will disappear when your program goes out of scope!
Well, the simple rule is that each variable constructed by new should be clean up by delete.
However depending on your goal, you may not need write the delete yourself.
At home, when learning the gory details of memory management, you will probably write as many delete as you write new.
Professionals, however, never use delete in applicative code (*). delete is a code smell. It's the shortest way to memory leaks in the presence of exceptions. Professionals use RAII to deal with exceptions safely, and namely: smart pointers/smart containers.
(*) as opposed to library code, ie someone wrote that shared_ptr class one day.