Memory Leaks without calling clear() on C++ STL container objects - c++

Suppose that I have a class Foo defined as follows.
If I don't have bars.clear() in ~Foo(), will this result in memory leaks?
I was wondering about this because bars is an object field ( not a pointer field ) so when ~Foo() is called, the destructor of std::vector should be automatically called so I was wondering whether the destructor of std::vector will transparently call .clear() or not.
class Foo
{
private:
std::vector<Bar*> bars;//object field
...
};
Foo::~Foo
{
//bars.clear();
}

std::vector::clear() delete the objects within std::vector and change its std::vector::size() to zero. If you create std::vector, RAII will take care resource release process but you have to wait until reach the out of scope of the vector. If before going out of scope, you need to clean up your vector you can use std::vector::clear().
But in your special case you are keeping pointer to objects inside std::vector, so RAII do delete the pointer but ignores the objects pointing to the pointer. So you have to do your own clean up for the objects pointing to the pointer either before going out of scope and RAII become active or before calling std::vector::clear()

clear() just resets the vector to size 0. It does not delete anything, if the Bar* in the vector bars need to be deleted, you have to do it yourself.

If you hope to protect yourself against memory leaks by calling the clear() method, then I have to disappoint you. If you use a vector with pointers you need to do something like this:
std::vector<Bar*> bars;
bars.push_back(new Bar());
// some work with bars
// ....
// end of bars usage:
// (probably inside ~Foo() )
for(int i=0; i<bars.size(); i++) delete bars[i];
Depending on your level of experience and your specific use-case you might be better of using:
std::vector<Bar> bars;
If you want to know whether the std::vector<...>::clear() method is called from within the destructor of the vector, then the answer is: Maybe but not necessarily and it really doesn't matter anyway.
If you're really curious, you might be able to check, what a destructor of a container class does by looking at the header file for the vector container template. If and how much implementation details of std library objects are visible to the user is highly dependant on the system you're running with. At work I happen to work on Solaris 10 machines. The std lib on those machines is an implementation from Hewlett Packard anno 1994, where a lot of the actual code used by the vector template is still visible:
~vector ()
{
__destroy(__start, __finish);
__value_alloc_type va(__end_of_storage);
va.deallocate(__start,__end_of_storage.data()-__start);
}
void clear()
{
erase(begin(),end());
}
iterator erase (iterator first, iterator last)
{
iterator i = copy(last, end(), first);
iterator tmp = __finish;
__finish = __finish - (last - first);
__destroy(i, tmp);
return first;
}

Related

C++ delete class variable from function

class Foo {
// some codes
}
class Bar {
// Constructor, Destructor
vector<Foo*> fooVector;
Foo* getFoo(long index)
{
return fooVector[index];
}
long addFoo(Foo* foo)
{
fooVector.push_back(foo);
return fooVector.size() - 1;
}
void removeFoo(long index)
{
delete fooVector[index];
}
}
This is my codes.
But I want to change removeFoo like
void removeFoo(long index)
{
Foo* foo = getFoo(index);
delete foo;
}
Is it right? I can't sure about this.
In my thought, It may delete foo variable.
Please tell me whether it is right or not.
If the memory for the pointer was allocated by new then yes that's how you free it. However, that won't remove the pointer from the vector, so afterwards your vector have an entry that no longer point to valid memory. You need to erase it from the vector.
Also note that in modern C++ there is seldom a need to use pointers anymore, except for polymorphism really. If you don't have pointers, you don't have to worry about freeing memory or stray pointers.
Using such method you are bypassing most of the benefits you gained from using vector. When removing elements by delete (which is valid in the case you described) you will rubbish your fooVector with non-valid data pointers to some undeclared/invalid memory areas.
It would be handy if, in addition, you showed us how you actually create fooVector elements.
In my opinion, both ways that you presented are valid in C++, but they will lead to hard-to-rely-on results and rubbish in your vector.

When to delete elements added to std::vector?

I'm new to C++ and have a question regarding memory management.
In the header, I have this:
std::vector<Obstacle::Obstacle*> obstacles;
and in the .cpp I do this:
Circle *circle = new Circle(x, y, radius);
obstacles.push_back(circle);
where Circle is a subclass of Obstacle.
My question is when should I call delete on the elements which are in the vector? I have heard each new should be balanced by a delete. Do I need to in the destructor loop through the vector and call delete on each element? Isn't there a more elegant way?
Thanks
You have to call delete on the elements before you clear the vector, or before the vector goes out of scope iff the vector owns the objects pointed at. A more elegant solution is to have the vector hold smart pointers. The particular type of smart pointer should depend on the ownership policy.
For example, a vector owning the pointed-at objects should use C++11 std::unique_ptr:
std::vector<std::unique_ptr<Obstacle>> obstacles;
Of course, all of the above is under the assumption that you actually have strong reasons to use pointers. Often the best solution is the simplest ones: hold items by value:
std::vector<SomeType> things;
Note that this doesn't apply in your case, where you are storing pointers to objects derived from a base class, since storing values of base type would result in object slicing.
Edit: One simple way to ensure the elements are deleted when the vector goes out of scope is to write a scope guard class:
template <typename CONTAINER>
struct PtrContainerGuard
{
PtrContainerGuard(CONTAINER& container) : c_(container) {}
~PtrContainerGuard()
{
for (typename CONTAINER::iterator it = c_.begin(); it != c_.end(); ++it)
delete (*it);
}
private:
CONTAINER& c_;
}
then
std::vector<Obstacle*> obstacles;
PtrContainerGuard<std::vector::Obstacle*> p(obstacles);
Why not use shared_ptr? You don't have to create new objects and worry about deleting them if you use them.
typedef shared_ptr<Obstacle> ObstaclePtr;
int main()
{
std::vector<ObstaclePtr> obstacles;
//Create objets using shared_ptr and push them in vector
ObstaclePtr obstacle1(new Circle());
obstacles.push_back(obstacle1);
ObstaclePtr obstacle2(new Circle());
obstacles.push_back(obstacle2);
//When vector obstacles goes out of scope here, all circles inside are destructed!
}
Yes, there is a more elegant way. Throw away all your pointers.
std::vector<Obstacle::Obstacle> obstacles;
Circle circle(x, y, radius);
obstacls.push_back(circle);
Nothing was new'ed, nothing needs to be deleted, you save a memory allocation, and access to the objects stored in the vector becomes more efficient.
Also, your code will no longer make the eyes bleed of more experienced C++ developers.
All in all, I call that a win. :)

map iterator erase not calling appropriate destructors

gameObjects is a std::map<sf::String,VisibleGameObject*>, and results is a std::map<sf::String,VisibleGameObject*>::iterator. When this runs:
return gameObjects.erase(results);
I expected the destructor of VisibleGameObject to run, which is:
VisibleGameObject::~VisibleGameObject(){
m_pSceneManager->removeSprite(name);
}
never runs, until the class which holds gameObjects is destroyed, which then runs:
GameObjectManager::~GameObjectManager(){
std::for_each(gameObjects.begin(),gameObjects.end(),GameObjectDeallocator());
}
struct GameObjectDeallocator{
void operator()(const std::pair<sf::String,VisibleGameObject*>&p) const{
delete p.second;
}
};
then it does run. Why doesn't it run in the first case?
Using SFML 2.0
Thanks
erase removes the pointers from the container, but does not call delete.
Suggestion:
change your map to simply be:
std::map<sf::String,VisibleGameObject>
i.e. objects not pointers to them
or:
use a shared_ptr/unique_ptr (e.g. boost::shared_ptr or std::shared_ptr depending upon availability):
std::map<sf::String,std::shared_ptr<VisibleGameObject> >
which will call the destructor
calling erase() won't free the pointer as the implementation(map) doesn't know how the object pointed to was allocated ((example: should it call delete or free?) and more importantly it doesn't own the pointer i.e you don't transfer ownership to the container when storing pointers.
Use std::unique_ptr to wrap you pointer and then store it in the container by value. This will aid garbage collection and give you what you need.
using VisibileGameObjectPtr = std::unique_ptr<VisibleGameObject>;
std::map<sf::String,VisibleGameObjectPtr> gameObjects;
// memory will be automatically garbage collected when you erase this item.
gameObject["key"] = VisibileGameObjectPtr(new VisibleGameObject(..args..));

How can I free a pointer vector?

How can I free up memory in a pointer vector?
Here's the code:
class A
{
private:
int x,y,z;
public:
A(param1, param2, param3)
{
x=param1;
y=param2;
z=param3;
}
~A()
{
//prompts an alertbox, warning me about the successful call of the destructor;
}
};
...
vector<A*> list;
list.push_back(new A(1,2,3));
list.erase(list.begin()+index);//SHOULD delete the object from the memory;
list.clear();
I found out that .erase() doesn't free up memory, neither calls the destructor; I tried to use delete on every list entry with an iteration, but crashes after one iteration. Already checked if the list entry was already NULL, to avoid any error.
Am I missing something?
Also, I must use only STL, don't need Boost.
list.erase will deallocate the memory for its member elements (and call their destructors, if they exist); it will not call delete on them.
A Boost shared_ptr would be the obvious way of doing this. If you don't want to use that, you're either going to write your own smart-pointer class, or iterate through list and call delete on each pointer before calling erase. You can do this neatly with something like:
void my_delete(A *p)
{
delete p;
}
...
std::for_each(list.begin(), list.end(), my_delete);
for( std::vector<A*>::iterator i = list.begin(), endI = list.end(); i != endI; ++i)
{
delete *i;
}
list.clear();
or, using new lambda functions
std::for_each( list.begin(), list.end(), []( A* element) { delete element; });
list.clear();
erase only erases what's in the vector (the pointers) without doing anything about what they might point at.
If you want what the point at deleted, you need to handle that yourself.
My advice would be to avoid handling any of this yourself, and consider using Boost ptr_vector instead.
Upon destruction, an STL container will destroy the objects it contains. If those objects are pointers, then it will destroy the pointers. For naked, dumb pointers, this will not delete the objects they point to. That's why it is usually best to use smart pointers for that. Smart pointers will delete the objects they refer to upon deletion; std::shared_ptr keeps track of copying pointers and how many references to a given object exist, and will only delete the object when the last pointer dies. This is always a good first candidate when looking for a suiting smart pointer. Your container would then be declared like this: std::vector< std::shared_ptr<A> >
However, your compiler/std lib might not come with std::shared_ptr, which is a feature of the next C++ standard, generally expected next year. It might, however, come with std::tr1::shared_ptr, which is a TR1 feature from 2003. (If all else fails, boost has boost_shared_ptr, but you already ruled out boost.)
You can manually manage dynamically allocated objects in STL containers, but it's a burden and prone to errors. For example, you must prevent functions from returning early (before the manual cleanup) through return statements or exceptions, and you must watch out for copy operations on containers. (Otherwise two containers would have pointers referring to the same objects, which you might then try to destroy twice.)
Manually managing resources is a PITA, prone to errors, and best avoided.
The code you have posted is not legitimate C++. Plus, erase does not delete objects you have allocated, it only erases contents of the vector, which in your case are pointers. The actual objects that you have allocated are not being deleted. Here is a correct way of doing what you want:
#include <vector>
#include <algorithm>
class A
{
int x,y,z;
public:
A (int param1, int param2, int param3) :
x (param1), y (param2), z (param3)
{
}
};
struct Deleter
{
template <typename T>
void operator () (T *obj) const
{
delete obj;
}
};
int
main ()
{
std::vector<A*> list;
list.push_back (new A (1, 2, 3));
list.push_back (new A (4, 5, 6));
list.push_back (new A (7, 8, 9));
std::for_each (list.begin (), list.end (), Deleter ());
list.clear ();
}
You may also look at Boost Ptr Container library that solves this problem in a safe and reusable manner. In C++0x, there is a std::unique_ptr template class that supports movable semantics and can be used with STL containers and algorithms to clean up memory automatically.
for(size_t i = 0; i < list.size(); ++i)
{
delete list[i];
}
list.clear();
If your make something like this and your code crashes, post exact code and crash information.

Example to use shared_ptr?

Hi I asked a question today about How to insert different types of objects in the same vector array and my code in that question was
gate* G[1000];
G[0] = new ANDgate() ;
G[1] = new ORgate;
//gate is a class inherited by ANDgate and ORgate classes
class gate
{
.....
......
virtual void Run()
{ //A virtual function
}
};
class ANDgate :public gate
{.....
.......
void Run()
{
//AND version of Run
}
};
class ORgate :public gate
{.....
.......
void Run()
{
//OR version of Run
}
};
//Running the simulator using overloading concept
for(...;...;..)
{
G[i]->Run() ; //will run perfectly the right Run for the right Gate type
}
and I wanted to use vectors so someone wrote that I should do that :
std::vector<gate*> G;
G.push_back(new ANDgate);
G.push_back(new ORgate);
for(unsigned i=0;i<G.size();++i)
{
G[i]->Run();
}
but then he and many others suggested that I would better use Boost pointer containers
or shared_ptr. I have spent the last 3 hours reading about this topic, but the documentation seems pretty advanced to me . ****Can anyone give me a small code example of shared_ptr usage and why they suggested using shared_ptr. Also are there other types like ptr_vector, ptr_list and ptr_deque** **
Edit1: I have read a code example too that included:
typedef boost::shared_ptr<Foo> FooPtr;
.......
int main()
{
std::vector<FooPtr> foo_vector;
........
FooPtr foo_ptr( new Foo( 2 ) );
foo_vector.push_back( foo_ptr );
...........
}
And I don't understand the syntax!
Using a vector of shared_ptr removes the possibility of leaking memory because you forgot to walk the vector and call delete on each element. Let's walk through a slightly modified version of the example line-by-line.
typedef boost::shared_ptr<gate> gate_ptr;
Create an alias for the shared pointer type. This avoids the ugliness in the C++ language that results from typing std::vector<boost::shared_ptr<gate> > and forgetting the space between the closing greater-than signs.
std::vector<gate_ptr> vec;
Creates an empty vector of boost::shared_ptr<gate> objects.
gate_ptr ptr(new ANDgate);
Allocate a new ANDgate instance and store it into a shared_ptr. The reason for doing this separately is to prevent a problem that can occur if an operation throws. This isn't possible in this example. The Boost shared_ptr "Best Practices" explain why it is a best practice to allocate into a free-standing object instead of a temporary.
vec.push_back(ptr);
This creates a new shared pointer in the vector and copies ptr into it. The reference counting in the guts of shared_ptr ensures that the allocated object inside of ptr is safely transferred into the vector.
What is not explained is that the destructor for shared_ptr<gate> ensures that the allocated memory is deleted. This is where the memory leak is avoided. The destructor for std::vector<T> ensures that the destructor for T is called for every element stored in the vector. However, the destructor for a pointer (e.g., gate*) does not delete the memory that you had allocated. That is what you are trying to avoid by using shared_ptr or ptr_vector.
I will add that one of the important things about shared_ptr's is to only ever construct them with the following syntax:
shared_ptr<Type>(new Type(...));
This way, the "real" pointer to Type is anonymous to your scope, and held only by the shared pointer. Thus it will be impossible for you to accidentally use this "real" pointer. In other words, never do this:
Type* t_ptr = new Type(...);
shared_ptr<Type> t_sptr ptrT(t_ptr);
//t_ptr is still hanging around! Don't use it!
Although this will work, you now have a Type* pointer (t_ptr) in your function which lives outside the shared pointer. It's dangerous to use t_ptr anywhere, because you never know when the shared pointer which holds it may destruct it, and you'll segfault.
Same goes for pointers returned to you by other classes. If a class you didn't write hands you a pointer, it's generally not safe to just put it in a shared_ptr. Not unless you're sure that the class is no longer using that object. Because if you do put it in a shared_ptr, and it falls out of scope, the object will get freed when the class may still need it.
Learning to use smart pointers is in my opinion one of the most important steps to become a competent C++ programmer. As you know whenever you new an object at some point you want to delete it.
One issue that arise is that with exceptions it can be very hard to make sure a object is always released just once in all possible execution paths.
This is the reason for RAII: http://en.wikipedia.org/wiki/RAII
Making a helper class with purpose of making sure that an object always deleted once in all execution paths.
Example of a class like this is: std::auto_ptr
But sometimes you like to share objects with other. It should only be deleted when none uses it anymore.
In order to help with that reference counting strategies have been developed but you still need to remember addref and release ref manually. In essence this is the same problem as new/delete.
That's why boost has developed boost::shared_ptr, it's reference counting smart pointer so you can share objects and not leak memory unintentionally.
With the addition of C++ tr1 this is now added to the c++ standard as well but its named std::tr1::shared_ptr<>.
I recommend using the standard shared pointer if possible. ptr_list, ptr_dequeue and so are IIRC specialized containers for pointer types. I ignore them for now.
So we can start from your example:
std::vector<gate*> G;
G.push_back(new ANDgate);
G.push_back(new ORgate);
for(unsigned i=0;i<G.size();++i)
{
G[i]->Run();
}
The problem here is now that whenever G goes out scope we leak the 2 objects added to G. Let's rewrite it to use std::tr1::shared_ptr
// Remember to include <memory> for shared_ptr
// First do an alias for std::tr1::shared_ptr<gate> so we don't have to
// type that in every place. Call it gate_ptr. This is what typedef does.
typedef std::tr1::shared_ptr<gate> gate_ptr;
// gate_ptr is now our "smart" pointer. So let's make a vector out of it.
std::vector<gate_ptr> G;
// these smart_ptrs can't be implicitly created from gate* we have to be explicit about it
// gate_ptr (new ANDgate), it's a good thing:
G.push_back(gate_ptr (new ANDgate));
G.push_back(gate_ptr (new ORgate));
for(unsigned i=0;i<G.size();++i)
{
G[i]->Run();
}
When G goes out of scope the memory is automatically reclaimed.
As an exercise which I plagued newcomers in my team with is asking them to write their own smart pointer class. Then after you are done discard the class immedietly and never use it again. Hopefully you acquired crucial knowledge on how a smart pointer works under the hood. There's no magic really.
The boost documentation provides a pretty good start example:
shared_ptr example (it's actually about a vector of smart pointers) or
shared_ptr doc
The following answer by Johannes Schaub explains the boost smart pointers pretty well:
smart pointers explained
The idea behind(in as few words as possible) ptr_vector is that it handles the deallocation of memory behind the stored pointers for you: let's say you have a vector of pointers as in your example. When quitting the application or leaving the scope in which the vector is defined you'll have to clean up after yourself(you've dynamically allocated ANDgate and ORgate) but just clearing the vector won't do it because the vector is storing the pointers and not the actual objects(it won't destroy but what it contains).
// if you just do
G.clear() // will clear the vector but you'll be left with 2 memory leaks
...
// to properly clean the vector and the objects behind it
for (std::vector<gate*>::iterator it = G.begin(); it != G.end(); it++)
{
delete (*it);
}
boost::ptr_vector<> will handle the above for you - meaning it will deallocate the memory behind the pointers it stores.
Through Boost you can do it
>
std::vector<boost::any> vecobj;
boost::shared_ptr<string> sharedString1(new string("abcdxyz!"));
boost::shared_ptr<int> sharedint1(new int(10));
vecobj.push_back(sharedString1);
vecobj.push_back(sharedint1);
>
for inserting different object type in your vector container. while for accessing you have to use any_cast, which works like dynamic_cast, hopes it will work for your need.
#include <memory>
#include <iostream>
class SharedMemory {
public:
SharedMemory(int* x):_capture(x){}
int* get() { return (_capture.get()); }
protected:
std::shared_ptr<int> _capture;
};
int main(int , char**){
SharedMemory *_obj1= new SharedMemory(new int(10));
SharedMemory *_obj2 = new SharedMemory(*_obj1);
std::cout << " _obj1: " << *_obj1->get() << " _obj2: " << *_obj2->get()
<< std::endl;
delete _obj2;
std::cout << " _obj1: " << *_obj1->get() << std::endl;
delete _obj1;
std::cout << " done " << std::endl;
}
This is an example of shared_ptr in action. _obj2 was deleted but pointer is still valid.
output is,
./test
_obj1: 10 _obj2: 10
_obj2: 10
done
The best way to add different objects into same container is to use make_shared, vector, and range based loop and you will have a nice, clean and "readable" code!
typedef std::shared_ptr<gate> Ptr
vector<Ptr> myConatiner;
auto andGate = std::make_shared<ANDgate>();
myConatiner.push_back(andGate );
auto orGate= std::make_shared<ORgate>();
myConatiner.push_back(orGate);
for (auto& element : myConatiner)
element->run();