I'm searching for a proper way to clean my pointers.
Here the example code:
class Parent {
protected:
int m_Var;
public:
Parent() : m_Var(0) {}
virtual ~Parent() {}
void PubFunc();
};
class Child : public Parent {
protected:
bool m_Bool;
public:
Child() : m_Bool(false) {}
virtual ~Child() {}
void ChildFunc();
};
void RemoveObj(Parent **ppObj)
{
*ppObj->PubFunc();
delete *ppObj;
ppObj = NULL;
}
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
RemoveObj(&pPObj);
RemoveObj(&pCObj); // This is line 33
return 1;
}
But the compiler gives error:
classes.cpp:33: error: invalid conversion from ‘Child**’ to ‘Parent**’
classes.cpp:33: error: initializing argument 1 of ‘void RemoveObj(Parent**)’
There are soo many ways to handle memory correctly.
The one close to your example would be:
template <typename T>
RemoveObj(T **p)
{
if (p == NULL) return;
delete *p;
*p = NULL;
}
Additionally you might want to use std::auto_ptr instead. It would look like:
int main()
{
std::auto_ptr<Parent*> pPObj(new Parent);
std::auto_ptr<Child*> pCObj(new Child);
// no deletes needed anymore
To put it simple :
Child is a subclass of Parent so that means that Child* can be substituted with Parent*
BUT
Child* is NOT a subclass of Parent* so that means that Child** can't be substituted with Parent**
"Child" and "Child*" are not the same types.
What you need to do is nullify all the pointers to the object you just deleted. The idea of pointers is that there will be more than one pointer storing the address of the same object. If not, there is little reason to use a bare pointer, and so the pattern you're trying to capture is not very useful - but you are far from the first person to try this. As other answers have mentioned, the only way to deal with pointers is to carefully control access to them.
The title of your question is absolutely correct! There's a good reason for it. A pointer identifies a location that stores an object of a specific type. A pointer to a pointer gives you the ability to change what object a pointer points to.
void Foo(Parent **pp)
{
*pp = new OtherChild();
}
Your Child class derives from Parent, and so does my OtherChild class. Suppose the compiler allowed you to do this:
Child *c = 0;
Foo(&c);
You expected that to work, but if it had, then we would now have a Child pointer c that in fact pointers to an instance of OtherChild. Who says those two types are compatible?
Again, this is a very frequent misunderstanding - it crops up repeatedly here for other languages, especially with regard to List<Parent> and List<Child> in C#.
You don't need a wrapper for delete, keep it simple:
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
delete pPObj;
delete pCObj; // This is line 33
return 1;
}
And remember you will run into issues deleting array type objects with your RemoveObj (since you are always using a scalar delete). An alternative is of course to pass a flag around to indicate you want delete []. But as I said: KISS.
If your problem is dealing with memory and resources, the best advice would be to forget your approach completely and use smart pointers. std::auto_ptr or boost::shared_ptr would be a start point.
If you hold all your heap allocated resources with smart pointers your code will be more robust.
You can find some useful information from the book < C++ common knowledge> Item 8. Pointers to Pointers.
Probably the most simple solution I have found:
#define __REMOVE_OBJ(pObj) RemoveObj(pObj); pObj = NULL;
And just call this one:
__REMOVE_OBJ(pPObj);
__REMOVE_OBJ(pCObj);
But I don't really like it myself...
From discussion on make shared_ptr not use delete
Shared pointer will ensure you cleanup when you should and that you don't access something that is destroyed. Further you can specialise and provide an alternate destruction method.
boost::shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );
Related
Assume we have the following very simple class:
class Item {
public:
Item(){};
virtual ~Item(){};
};
and the class ItemHolder which holds a pointer to an instance of Item. I want ItemHolder to only hold a pointer to the actual data and not copy anything internally. Therefore, I guess this is how ItemHolder should look like:
class ItemHolder {
public:
ItemHolder(){
Q = NULL;
}
ItemHolder(Item &QQ){
Q = &QQ;
}
virtual ~ItemHolder() {
// Don't delete Q!
// The caller is responsible for the fate of Q...
}
private:
Item *Q;
};
However, I guess that this design suffers from certain pathologies which in C++11 are handled with smart pointers. For instance one could expect that the following code would delete a as well, but this is not the case:
Item *a = new Item();
ItemHolder *q = new ItemHolder(*a);
delete q;
What is more, I more often than not meet the following constructor pattern:
ItemHolder(const Item &QQ){
Q = new Item(QQ);
}
accompanied by a destructor like this:
virtual ~ItemHolder() {
if (Q != NULL){
delete Q;
Q = NULL;
}
}
All this may (and will) create ambiguity regarding who is responsible for the memory management of the various objects. What are the commonly employed best practices when it comes to instantiating pointers in C++98 (given that I don't want to create any copies of other variables using new or a copy-constructor)?
So I have a C++ function to which I pass a pointer to a base class, like:
void DoStuffAndAssignPtr(MyBase* ptr)
{
MyBase* p;
//do stuff
if (stuff was awesome) p = new MyAwesome();
else p = new MyBase();
//vftable of p before the return is MyAwesome
(*ptr) = (*p);
}
Now we need to invoke some virtual method that 'MyAwesome' and 'MyBase' implement differently. However, when checking the return value, as below:
void mainly()
{
MyBase* passMe = new MyBase();
DoStuffAndAssignPtr(passMe);
//now passMe is always being returned with MyBase's vftable
}
We can see that 'passMe' is always a 'MyBase' (as far as the vftable shows while debugging in VS). Can anyone provide any guidance as to why this is happening, and how I can ensure that 'passMe' will invoke 'MyAwesome' implementations of virtual methods?
The problem is with the use of (*ptr)=(*p). You should use ptr=p.
Only pointer and reference have polymorphism. When you use dereference (the star *), you lose this property, and only the base part is copied from p to ptr. This is because ptr only have space for that part of information.
You have object slicing issue, below statement slices MyAwesome object to MyBase:
(*ptr) = (*p)
You only pass MyBase* to DoStuffAndAssignPtr and tried to allocate a new pointer which will only overwrite the copy of function parameter. You need to pass the reference of the pointer instead.
void DoStuffAndAssignPtr(MyBase*& ptr);
^^^
Also as passMe is allocated by new outside DoStuffAndAssignPtr already, you created another membory for ptr inside DoStuffAndAssignPtr which will cause memory leak.
A better solution is:
MyBase* MakeAClass()
{
if (stuff was awesome)
{
return new MyAwesome();
}
return new MyBase();
}
int main()
{
MyBase* passMe = MakeBase()
}
I'm using shared_ptr<Base> for some sort of tree list with derived classes. But I'm getting a pointer acces violation when my tree gets destructed.
My code looks something like this, besides, this actually similates my runtime error:
#include <iostream>
#include <memory>
#include <vector>
class Base;
typedef std::shared_ptr<Base> pBase;
class Derived;
class Base {
public:
std::vector<pBase> children;
pBase parent;
Base() {}
virtual ~Base() {}
virtual void doSomething() {}
void add(pBase i);
};
class Derived : public Base {
void doSomething() {
// Do something...
}
};
void Base::add(pBase i) {
i->parent = pBase(this);
children.push_back(i);
}
int main() {
pBase tree = pBase(new Derived());
pBase child(new Derived());
child->add(pBase(new Derived()));
tree->add(child);
}
Also when I add the following lines to Base::~Base:
std::cout << "destruct " << name << std::endl;
And implement a std::string called name in Base which is different for each instance, I can see that the destructor is called multiple times (because of the Base::parent reference I think). That ofcourse triggered my error, but I still don't understand why it happens because shared_ptr<Base> is expected to count its references before actually destroying it!!?
I hope some can tell me what I'm doing wrong!
But more important, how I can fix this!
Look at this line in add()
i->parent = pBase(this);
Each time you call add, you're creating a new shared pointer to this. These shared pointer are separate - that is, they are NOT 'shared' as you think. So, the first time you delete a child, it's parent gets deleted (because it's a shared pointer). Hence your code blows up.
Try (as a start) making parent a plain dumb pointer.
Base *parent;
Just to add to the others' answers: The canonical way to do what you want in the line
i->parent = pBase(this);
is to use std::enable_shared_from_this. You
Derive Base from it
class Base : std::enable_shared_from_this<Base> {
Ensure that every Base instance is owned by a std::shared_ptr. That is OK in your case, since you create the objects in expressions like
pBase child(new Derived());
Use shared_from_this() instead of this when you want a std::shared_ptr. The problematic line will then become
i->parent = shared_from_this();
Here
i->parent = pBase(this);
you create a smart pointer from a plain old pointer to an object which you didn't get directly from new. Never do this.
As #Roddy explained, you get separate smart pointer objects, with separate reference counters. Two reference counters for one pointee won't work.
In your case, it's probably ok to make parent a normal pointer, as #Roddy proposed. This way, you don't get in trouble with cyclic references. Just be sure that you never access the parent pointer after you deleted the parent. No problem if you delete all the children together with the parent (which happens automatically, unless you store more smart pointers to them, somewhere else)
If you want to initialize a smart pointer, you've got two choices, basically: Use smart pointers in every interface. Unfortunately that doesn't work for "this" because that's an implicit parameter. You would need to pass the smart pointer, which you already created, to the method manually, in an extra parameter. Like this:
tree->add(tree, child);
Which is kind of ugly, so you may want to consider making "add" a static method, so you won't need to pass the parent twice.
The other choice: Use another kind of smart pointer, like boost::intrusive_ptr, where you can store the reference count in the pointee. This way, you are able to find the reference count, even if you've got only a dumb pointer like "this".
Edit: The answer by #jpalecek, below, is better. Use that one. Sebastian.
I wanted to make a special version of shared_ptr that would perform specific operations when it was created or destroyed, but my plans appear to be foiled by the realization that shared_ptr's destructor is non virtual, meaning when I override it, my pointers never get cleaned up when the last instance of them are destroyed.
The only alternative that comes to mind is to build in this behavior into every class that I want to use with my hypothetical custom shared_ptr, and that's not feasible (or possible in some cases).
Edit:
The reason I want this is because I want to use some classes as userdata objects in lua, and I want each one of my objects that I use this way to have a fenv table unique to it that will be cleaned up when all references to the object have been removed. I plan on using the address of the pointer as they key into a table that holds the fenv table.
Lets say I have a widget that can have other widgets as children. I create two widgets in Lua, then set one as the child of the other and remove all lua references to the child widget (the fact that it's a child is handled in C++). The GC can now run at any time and remove the child. I don't necessarily want the child to have it's destructor run though, so I want to make it a shared_ptr. That way, C++ objects can still use it after Lua has cleaned it up. If I've assigned values or functions to it's fenv I still want to be able to access them. Only when the final reference to my child widget is removed do I want the fenv tabled to be removed totally.
It already has this ability built in without the need to let people do dangerous things like derive from it:
#include <boost/shared_ptr.hpp>
#include <iostream>
/*
* Done as a function for simplicity.
* But this can be done in so many ways
*/
void MyCleanup(int* x)
{
std::cout << "DONE\n";
delete x;
}
int main()
{
boost::shared_ptr<int> x(new int(5), MyCleanup);
}
Problem with deriving:
Just off the top of my head.
class X: public shared_ptr<int> { /* STUFF. With a special destructor. */ };
int main()
{
/* what happens now? Similar to slicing but not quite */
X data1(new int(5));
shared_ptr<int> data2;
shared_ptr<int> data3(data);
data2 = data1;
}
Just make a wrapper object; much easier. You can have the wrapper object have a shared_ptr instance inside it, and still use the allocation address of the internal object as an index. This seems much better than mucking around with derivation or custom cleanup routines, unless I'm missing something.
Eg:
class CWrapsLuaObject
{
CWrapsLuaObject( LuaObject* pObject )
{ [assign internal ptr, do mapping, etc.] }
shared_ptr< LuaObject > m_spObject;
[...]
};
shared_ptr< CWrapsLuaObject > spInstance( new CWrapsLuaObject( pObject ) );
Am I missing why this would not be the easiest solution (not taking anything away from the other suggested solutions, which could also work)?
You can provide a custom deletion object to be used with the shared_ptr. If you're trying to stick extra information into the shared_ptr, you may be better putting it into the deletion object. It doesn't feel very clean to me, but it works.
class ExtraThingToDestroy
{
public:
~ExtraThingToDestroy() { std::cout<<"Destroying the extra thing"<<std::endl; }
};
template<typename T>
class CustomDestructor
{
public:
CustomDestructor( ExtraThingToDestroy * v ) : v_(v) {}
void operator()( T* t ) { delete t; delete v_; }
ExtraThingToDestroy * v_;
};
main()
{
shared_ptr<int> ptr( new int, MyExtraDestructor<int>( new ExtraThingToDestroy ) );
shared_ptr<int> ptr2 = ptr;
//Now when ptr and all its copies get destroyed,
// the ExtraThingToDestroy will get deleted along with the int.
}
if you derive the class your_shared_ptr from shared_ptr and override the destructor, your destructor should be called in code like this:
{
your_shared_ptr<int> x(new int);
}
If you use it like this, instead:
{
shared_ptr<int>* ptrptr = new your_shared_ptr<int>(new int);
}
then it won't, but do you really need that?
Or am I misunderstanding something?
This is a C++ class that I have made with n number of pointers.
class SomeClass
{
private:
int* ptr1;
int* ptr2;
...
int* ptrn;
private:
// constructors, destructors, and methods
};
During the initialization stage, I want to make all those pointers point to NULL (or make pointers point to NULL by default when they are declared) rather than doing so:
void SomeClass::MakePtrNull()
{
ptr1 = NULL;
ptr2 = NULL;
...
ptrn = NULL;
}
Is there any easy method of accomplishing this goal? I'm just wondering if there are any ways of avoiding typing n lines of ptr = NULL; in my function. Thanks in advance.
ADDED based on the answers that I have received so far:
Unfortunately, those pointers have to be separate, as they are used for different purposes. I made the names of the pointers as such just to make a point of what I'm trying to do, but each pointer has a completely different purpose. I guess I would have to make them point to NULL as I have done already. Thanks for your answers.
Instead of int *, create a smart-pointer-like class which works exactly like a int *, but default-constructs with NULL:
template <typename T>
class MyPointer {
T *p;
public:
MyPointer() : p(NULL) { }
MyPointer(T *o) : p(o) { }
operator T*() const { return p; }
// ...and the rest of the traditional smart-pointer operators
};
Then, use it in your class:
class SomeClass
{
private:
MyPointer<int> ptr1;
MyPointer<int> ptr2;
...
MyPointer<int> ptrn;
private:
// constructors, destructors, and methods
};
Every variable of the MyPointer<int> type will be automatically initialized correctly in SomeClass's constructors, without the need for any extra typing. If you did not forget or incorrectly implement any of MyPointer's methods, it will act exactly like a normal pointer, and have the exact same size and performance.
Why don't you use an array or a vector rather than creating n individually named pointers? Then you can do the nulling in a short for loop.
You can do this:
void SomeClass::MakePtrNull()
{
ptr1 = ptr2 = ptr3 = ... = ptrn = NULL;
}
First, the technique that does not work:
Calling memset to set the entire object to zero won't do. First, it'll cause a lot of trouble if your function has one or more virtual functions, and second, a null pointer is not guaranteed to be represented by a bit pattern of all zeros.
What I would probably do in your case is store the pointers in an array or a vector.
Then you can use the std::fill function to set them all to NULL. (Or you could use a loop if you prefer)
Of course, if you need to do this often enough, it may be worth writing a wrapper class which behaves as the pointer, but which sets it to NULL in its default constructor.
Or you could use boost::optional which works essentially like this. (although it is not specific for pointers)
I recommend you to do the following, if you have to keep the pointers separately (probably the most pressing need would be if the pointers can have different types)
class SomeClass {
struct Pointers {
int* ptr1;
int* ptr2;
float* ptrn;
} ptrs;
public:
void MakePtrNull();
};
void SomeClass::MakePtrNull()
{
// clears all pointers at once
ptrs = Pointers();
}
This does work, because value-initialization for classes that doesn't have a user declared constructor will value initialize all its members. Value initialization of a pointer will create a null pointer.
Why not use a default constructor:
SomeClass::SomeClass() : ptr1(NULL), ptr2(NULL), ...
{
}
You could also do:
ptr1 = ptr2 = ptr3 = NULL;
You could put the pointers into a struct and then memset() the struct when needed. The pointers are still separated, but you have the means of targeting them as a single unit without affecting the rest of your class. For example:
struct MyPointers
{
int* ptr1;
int* ptr2;
...
int* ptrn;
};
class SomeClass
{
private:
MyPointers ptrs;
...
};
void SomeClass::MakePtrNull()
{
memset(&ptrs, 0, sizeof(ptrs));
}
Use a vector for this (because by the sounds of it you won't need to ever edit the list in the future - and you need random access). You can do it like this:
class PointerList
{
private:
typedef std::vector<int*> IntPtrVector;
IntPtrVector m_ptrVec;
public:
PointerList()
{
m_ptrVec.reserve(5);
for (int i = 0; i < 5; i++)
m_ptrVec.push_back(NULL);
}
int* getPointer(int index)
{
return m_ptrVec[index];
}
void setPointer(int index, int* ptr)
{
assert(index <= 4);
m_ptrVec[index] = ptr;
}
};
EDIT
Though to be honest this reeks of ghettoness. Are you sure your problem requires this solution? If you elaborate more on your specific problem, in another question perhaps, I'm sure you can get some better answer on how to accomplish what you want more elegantly - rather then by creating a second problem.