This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to properly delete pointer?
i'm using std::vector to put a group of objects into it for later use, i am using DETAIL* pPtr = new DETAIL to create the pointer, and then inserting it into the vector.
the struct of DETAIL
struct DETAIL {
int nRef;
short sRandom;
};
Is this the best way to delete and erase a pointer within a vector leaving no room for memory leaks?
while(Iter1 != m_Detail.end())
{
if((*Iter1)->nRef == m_SomeVar)
{
delete *Iter1;
m_Detail.erase(Iter1);
break;
}
Iter1++;
}
Don't put raw pointers into the vector, instead use smart pointers such as std::shared_ptr. Then there is no need for delete, simply erase the pointer from vector and the pointed object will be automatically deleted.
My suggestion would be to use std::shared_ptr remove the shared pointer from the vector using erase and let it take care of deallocation. However there is nothing wrong with what you are doing but erase does not cause the vector to release the space it has allocated to hold the pointer. You can use shrik_to_fit to remove that allocated space.
i am using DETAIL* pPtr = new DETAIL to create the pointer
That's your first mistake, you're acquiring a resource (memory from the freestore and an object constructed in that memory) and not initializing an object that will take ownership and guarantee to deallocate the resources you acquired. The idiom to solve that first mistake is called Resource Acquisition Is Initialization.
It should be something like:
std::shared_ptr<DETAIL> pPtr(new DETAIL);
Or better yet:
std::shared_ptr<DETAIL> pPtr = std::make_shared<DETAIL>();
Or in C++03 replace std::shared_ptr with boost::shared_ptr (and boost::make_shared)
The next mistake is delete *Iter1; because almost any code that uses delete outside of a destructor is wrong (and all code that uses delete outside a destructor and is accompanied by a question about how to avoid memory leaks is definitely wrong.) If you use the RAII idiom you don't need to use delete because it happens automatically at the right time.
Also, why is your class called DETAIL? What's wrong with Detail instead?
I don't like answer like "never do" so I'll answer, but gives you some tricks to bypass the risk of freeing the vector without freeing the content.
if I understand well you have a vector of DETAIL pointers:
std::vector<DETAIL*> details;
So you want a method to remove and delete all pointed objects which refer to a certain m_SomeVar: (for now let's imagine it's a free function)
void free_references(int reference, std::vector<DETAIL*> & vector)
{
std::vector<DETAIL*>::iterator it = vector.begin();
while (it != vector.end())
{
if ((*it)->nRef == reference)
{
delete *it;
// erase() makes the original 'it' in an unknown state which can't be used
// erase will return a valid iterator which is, in this case, the following element
it = vector.erase(it);
}
else
{
++it;
}
}
}
As I understand in your code, the vector is member of a class. Which is good cause you'll be able to delete everything in the destructor.
However, I would use std::unique_ptr here to "give" the ownership of the pointer to the unique_ptr container inside the vector. And when the vector memory is free, the std::unique_ptr smart point make sure that the owned pointed object is freed.
I don't know if i fully understood it but have you tryied using the ZeroMemory macro?
Related
I was thinking about a this situation not for a real implementation but to understand better how pointers works.
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
Ok, I know that have no sense to copy v[i] inside an other pointer, but I was thinking: copy do a memory leak?
After the execution of doComplexThings(), copy will continue to exist and will occupy space in the heap?
After deleting all elements it will continue to exist and point to a deallocated memory?
So logically if I do this things with complex objects I'll keep occupy the memory with unreference object? Or copy is saved in the stack because I don't use new? And at the end of doComplexThings it will be deleted?
I'm a bit confused, thanks!
There is some confusion on the topic of pointers in the C++ community. While it is true that smart pointers have been added to the library to alleviate problems with dynamic memory allocation, raw pointers are not obsolete. In fact, whenever you want to inspect another object without owning it, you should use a reference or raw pointer, depending on which suits your needs. If the concept of ownership is unclear to you, think of an object as being owned by another object if the latter is responsible for cleaning up afterwards (deleting the former).
For example most uses of new and delete should be replaces with the following (omitting std for brevity):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
Notice how a function that takes a T* doesn't need a smart pointer if it doesn't keep a copy of the T* it is given, because it doesn't affect the lifetime of the object. The object is guaranteed to be alive past the return point of do_stuff_with_T() and its function signature signals that it doesn't own the object by taking a raw pointer.
On the other hand, if you need to pass the pointer to an object that is allowed to keep the pointer and reference it later, it is unclear when the object will need to be destroyed and most importantly by whom. This is solved via a shared pointer.
ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
So how does the above factor in to your code. First of all, if the vector is supposed to own (keep alive) the ints it points to, it needs to hold unique_ptr<int> or shared_ptr<int>. If it is just pointing to ints held by something else, and they are guaranteed to be alive until after the vector is destroyed, you are fine with int*. In this case, it should be evident that a delete is never necessary, because by definition your vector and the function working on the vector are not responsible for cleaning-up!
Finally, you can make your code more readable by changing the loop to this (C++11 which you've tagged in the post):
for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
Again this is only true if some other object holds the ints and releases them, or they are on the stack but guaranteed to be alive for the whole lifetime of vector<int*> that points to them.
No additional memory is allocated on the heap when you do this:
copy = v[i];
variable copy points to the same address as v[i], but no additional array is allocated, so there would be no memory leak.
A better way of dealing with the situation is to avoid raw pointers in favor of C++ smart pointers or containers:
std::vector<std::vector<int>> myVector;
Now you can remove the deletion loop, which is an incorrect way of doing it for arrays allocated with new int[length] - it should use delete[] instead:
delete[] myVector[i];
Basically you're illustrating the problem with C pointers which lead to the introduction of C++ unique and shared pointers. If you pass a vector of allocated pointers to an opaque member function, you've no way of knowing whether that function hangs onto them or not, so you don't know whether to delete the pointer. In fact in your example you don't seem to, "copy" goes out of scope.
The real answer is that you should only seldom use allocated pointers in C++ at all. The stl vector will serve as a safer, easier to use version of malloc / new. Then you should pass them about as const & to prevent functions from changing them. If you do need an allocated pointer, make one unique_ptr() and then you know that the unique_ptr() is the "owner" of the memory.
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've defined a C++ class with the following header file:
class EarleyParser
{
public:
EarleyParser();
virtual ~EarleyParser();
void initialize( string filePath, bool probabilityParse );
private:
bool probabilityParser;
typedef unordered_map< string, list<Production>* > productionHashTable;
productionHashTable earlyHashTable;
};
As you can see a member element of the class is an unordered_map whose key element is a string and content element is a pointer to a list of objects of another class named Production (don't mind it, it could be anything).
My question is if I should leave it to the default destructor to free memory allocated, or if I should manually inspect the hash table and delete all of its elements.
In the second case what would be the procedure? Calling this for each element will be ok?
EarleyParser::productionHashTable::const_iterator got = this->earlyHashTable.find( "key" );
delete[] got->second;
You need to clarify who owns the list<Production> objects owned by EarlyParser. If EarlyParser owns them, then you need to free the resources. You can do it by iterating over the list and calling delete on each dereferenced iterator (not delete[]). Or you can store unique_ptr<list<Production>> instead. On the other hand, the simplest solution is to store list<Production> unless you really have very strong reasons for storing pointers.
If you're going to store pointers to anything in your map, you'll have to manually go through the map and delete each one. Normally in a class you'd stick to RAII (Resource Acquisition is Initialization) and construct things in the constructor and destroy in the destructor
for (;;)
delete map->second; //it's not an array of lists
However a pointer to a container is NOT a good idea. Why do you do need a pointer? What problem are you trying to solve using a pointer to a list?
Using a smart pointer like std::unique_ptr is a much better idea than raw pointers. Raw pointers should be a last resort, not the first thing you grab when you can't think of anything better.
Use a:
typedef unordered_map< string, std::unique_ptr<list<Production> > > productionHashTable;
instead. Then you don't need to worry about managing memory.
The compiler synthesized destructor is not going to delete dynamically allocated lists you put in your map, so you have to do it yourself. In this case you can just iterate through your map and delete the second member of each element:
EarleyParser::~EarleyParser() {
for ( productionHashTable::iterator i = earlyHashTable.begin(); i != earlyHashTable.end(); ++i )
delete i->second;
}
A better approach would be to put lists in your map rather than pointers to lists. In that case the compiler would automatically take care of destruction, as in:
typedef unordered_map< string, list<Production> > productionHashTable;
Unordered_map's destructor actually calls the destructors of the object it has, which means that the destructor's of the lists will be called.
The destructor of std::list has this note:
Note, that if the elements are pointers, the pointed-to objects are not destroyed.
So this means, you will have to clear that memory yourself. Yes, going through the container and deleting elements 1by1 is fine. As other answerers mentioned, holding pointers like this is not a good idea though.
Since you're using a raw pointer to the std::list you'll have to delete it yourself either during the lifecycle of the map or when you clean up the EarleyParser object in its destructor.
You could use something like this in your destructor:
for ( auto it = productionHashTable.begin();
it != productionHashTable.end(); ++it )
{
delete it->second;
}
productionHashTable.clear()
Note that the last line isn't strictly necessary as it will be cleared anyway as the EarleyParser object is destructed but clearly you mustn't use the values in the map after you've deleted them!
So I decided to have some pointer fun tonight :)
CursorHBList::CursorHBList(UINT iNumHB)
:m_ppCursorHB(nullptr)
,m_iNumHB(iNumHB)
{
if (iNumHB != 0) {
m_ppCursorHB = new CursorHitBox* [iNumHB];
}
}
so you can see, I've now dynamically allocated pointer-types.
Those pointers will each point to another (single) object in the heap. (later on, not in code sample)
So I've been wondering if I should delete all the pointer-to-object-types pointed to by the pointer-to-pointer-type first, and then delete[] the pointer-to-pointer-type?
Or is there a better way?
EDIT: Without using smart pointers...
As suggested, a better way would be using a container of smart pointers.
However, since you can't use smart pointers (I don't know why because all a smart pointer is is a very simple class, you could write your own), you'll need to loop through the array and delete each pointer, then delete[] the array, in that order. That's just what you have to do when you manage your own memory.
Is the following C++ code a memory leak?
list.push_back(new String("hi"));
As I understand it, push_back from any std collection/container always makes a copy. So if the new string is copied, nothing can ever delete the new'd string right? since there is no reference to it after the push_back...
Am I correct or wrong here?
Thanks.
Jbu
edit: I think I am wrong, since new will return a pointer...we'll always have the pointer to be able to delete the new String
Yes, but not for the reason you think.
Depending on how list is defined and initialized, push_back might throw an exception. If it does, the pointer returned from new is lost, and can never be freed.
But assuming push_back returns successfully, it stores a copy of the pointer returned by new, and so we can free the memory later by calling delete on that copy, so no memory is leaked as long as you do call delete properly.
No, the vector stores pointers and the copy is made of the pointer. You can delete the object any time later.
(You may get a leak, if the statement happens to throw an exception and you don't catch and handle it properly. That's why you might consider using smart pointers.)
If I saw this code I would be very suspicious a memory leak was possible. On the surface it appears to be adding an allocated String* into a list<String*>. In my experience this is often followed by bad error handling code which does not properly free the allocated memory.
While this dangerous in many circumstances it is not necessarily a memory leak. Consider the following example:
class Container {
~Container() {
std::list<String*>::iterator it = list.begin();
while (it != list.end()) {
delete *it;
it++;
}
}
void SomeMethod() {
...
list.push_back(new String("hi"));
}
std::list<String*> list;
}
In this code there is no leak because the containing class is responsible for the memory allocated and will free it in the destructor.
EDIT
As aschepler pointed out there is still a leak if the push_back method throws an exception.
You are correct, provided nothing deletes the string when it is removed from the list.
Yes, this is a memory leak unles you somehow take steps to delete the contained pointers.
And the best way to accomplish that is to use a smart pointer. For example, Boost's shared_ptr or C++0x's shared_ptr.
list.push_back(new String("hi"));
Why are you allocating dynamic strings in the first place? Unless you want to communicate between different parts of your program by changing strings (which would be quite unusual), get rid of the pointer:
std::list<std::string> list; // note: no pointer!
list.push_back(std::string("hi")); // explicitly create temporary
list.push_back("hi"); // alternative: rely on coercion
No.
You can delete the object by doing:
delete list[i];
list.erase(list.begin() + i);
or clear the whole list by:
for (unsigned int i = 0; i < list.size(); ++i)
{
delete list[i];
}
list.clear();