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.
Related
So, I am trying to do something like this
template <typename T>
void call(std::shared_ptr<Base<T>> b) {
}
int main() {
std::shared_ptr<Derived<int>> d = std::make_shared<Derived<int>>();
call(d);
}
It cant resolve the inheritance because they are shared pointers. Ideally I don't want to use static_pointer_cast or something like that in main so I was looking for maybe a different way to cast it so that the user in main can still call the same function but not have to worry about casting.
My second approach was to use raw pointers so I tried something like this:
template <typename T>
void call(Base<T> * b) {
std::shared_ptr<Base<T>> obj(b);
}
int main() {
std::shared_ptr<Derived<int>> d = std::make_shared<Derived<int>>();
call(d.get());
}
Since Base is an abstract class I can't use make_shared so I have to do it this way to my knowledge but the problem then becomes that as soon as the call function's scope ends it deletes the pointer resulting in a double free error since the shared ptr in main also tries to delete this.
Are there any suggestions for something to try?
First, it is a bad practice to use smart pointers wherever the ownership is not needed. In your case the main function owns the pointer, and there is no way the object is destroyed while the call function is being executed. So you may pass a raw pointer without problems (and that is even better because the interface doesn't require more than it needs). This however may not be true in case of multithreaded environment or if the call function has side effects storing the pointer (e.g. that is actually a set method if a class). In this case shared_ptr should be used indeed.
Next, you may create a shared_ptr<Base> initializing it with a pointer to Derived. You even don't need to have virtual destructor for deleting the object: shared_ptr knows the actual type:
{
std::shared_ptr<Base> d = std::make_shared<Derived>();
// Ok to delete
}
Finally, there is no problem in casting shared_ptr<Derived> to shared_ptr<Base>. That is another instance of a shared pointer that points to the same counter.
Problem summary
I don't know how to create an object of a derived class with the new-operator through a function (not a constructor), and have a base class pointer point to it.
Setup
I have an abstract base class and a derived class in my project:
class Base
{
// stuff
};
class Derived : public Base
{
//stuff
//constructor:
Derived(args);
};
I also have function that returns a Derived object.
Derived func(args);
At some point, I declare a base class pointer
Base* ptr = { nullptr };
and I want it to point to a Derived object later-on.
What I want
I want to create a Derived object using func, and be able to access it through the pointer ptr later in the code.
What I did so far
I know that it works to use the derived class's constructor
ptr = new Derived(args);
or simply its default constructor, if it exists
ptr = new Derived;
However, I have good reasons why I cannot use the constructor in my case, since the configuration of the derived object is more complicated. In this case I want to create this object with the function func.
I know that this,
ptr = new func(args);
does not work, since new expects a type. How can I achieve a behavior like this?
Thanks in advance for any advice and helpful replies.
Note: I'm using new since I need to access the Derived object also outside the scope of its creation.
Return a pointer from func might be the best option, but if you cannot modify func then ptr = new Derived(func(args)) might work. This requires that Derived has a copy constructor or a move constructor.
Derived * func(args)
{
Derived *p = new Derived();
// do your custom stuff:
p->x = args->i;
p->y = 3;
// return the pointer
return p;
}
// ...
ptr = func(args);
Dont forget to delete ptr later. To be able to call the destructor of Derived, using the pointer to Base later, you have to make the destructor virtual.
class Base
{
// ...
virtual ~Base();
};
You might want to look into writing your func as
template<class T, class TA>
boost::shared_ptr<T> func(TA args) { return boost::make_shared<T>(args); }
or
template<class T, class TA>
std::shared_ptr<T> func(TA args) { return std::make_shared<T>(args); }
if you want to generalize it for any compatible class and argument types. You may also want to typedef the shared pointer for better readability.
The shared pointer will also take care of object lifetime.
Solution summary
First of all, thanks to everyone who responded. The advice came incredibly fast and was very helpful and instructive.
I don't know if this is against some convention, but since there were multiple very different solutions, I would like to summarize them. (If I should rather put this as an edit to the question, please let me know).
All three solutions should work, and I use solution 2 for now. However, I might switch to solution 3 after learning more about smart pointers.
Solution 1 - by Alex and Daniel Langr
[link to reply]
Changing the function func such that it returns a pointer.
Derived* func(args)
{
Derived *p = new Derived();
// do some complicated configuration
return p;
}
Afterwards, I can use the function to directly define the pointer ptr.
ptr = func(args);
Alex also made some important remarks about how to delete the ptr later.
While this works very well, I chose not to follow this path, since I would like to avoid changing the return value of func.
Solution 2 - by Mestkorn
[link to reply]
Use the copy constructor.
This is maybe the simplest solution. By using the copy constructor, I can simply write
ptr = new Derived( func(args) );
While this requires a copy/move constructor, it worked perfectly well with the default copy constructor in my project. I didn't have to implement anything new. This is the solution I have in my code for now.
Solution 3 - by DNT
[link to reply]
Use smart pointers, more specifically a shared_ptr (Either std::shared_ptr or boost::shared_ptr.) This concept is completely new to me. Thanks for that!
I will learn more about this and might switch to this option, since it sounds like a cleaner solution. If I understand correctly, the advantage over the other two solutions is that I don't have to think about memory leakage or deleting the pointer.
Once I figured this out properly, I will come back and extend this summary.
I want to return an implementation of a class from a function. The function is in a library. I want to prevent the user from destroying the objects I return. How can I achieve this?
EDIT: Example.
Interface to the world:
class Base
{
public:
virtual void foo() = 0;
};
Base* GetFoo();
Implementation - Internal:
class Bar : public Base
{
public:
void foo() { //Do something}
};
Base* GetFoo()
{
return new Bar
}
You could use a private destructor and create some method (release()) to allow the object to be freed in a controlled manner.
Private destructors
What is the use of having destructor as private?
And to answer your question as you are deriving from base, so you cannot make base destructor private. You can achieve your goal by protected destructor.
Return a shared_ptr<Base> and keep a copy of the pointer yourself. That pointer will keep the object alive, no matter what the user will do with his shared_ptr<Base>. You might even consider returning a weak_ptr<Base> instead, to stress that the lifetime of the object is subject to your whims only.
Why would you want to do that? The user should be getting a copy of the returned object anyway, and it should be up to them whether to allocate or deallocate the copy.
You cannot prohibit the user of your library to shoot himself in a leg while cleaning a loaded gun. I.e. even if you return a constant reference, one could take address from it and then delete it. So you should make your code stable even in this situation.
P.S. private destructors (#nc3b) impose limitations on a further usage of the class (no more local non-dynamic instances, for example), so consider them wisely.
If what you're returning is a new object, then there is no reason why you should need to prevent the user from delete ing it.
However, you shouldn't leave any question about responsibility for deletion. Instead, either use a smart pointer to return the value, or use the polymorphic pImpl pattern (wherein a non-polymorphic wrapper contains a smart pointer to a polymorphic implementation - typically a smart pointer that provides value semantics, such as this ) instead of just returning a derived instance.
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?
I recently reworked one of my own libraries to try out separating interface from implementation. I am having on final issue with a class that is meant to return an instance of another class.
In the interface definition, I do something like
struct IFoo
{
virtual const IBar& getBar() = 0;
}
and then in the concrete Foo getBar looks like
const IBar& Foo::getBar()
{
Bar ret = Bar();
return ret;
}
The problem is ret gets deleted as soon as getBar is done, causing a big crash when the copy constructor tries to use Bar like so
const Bar myBar = myFoo.getBar();
I have been reading various things, and I know returning by reference is frowned upon, but I do not see any other way (I do not want to return Bar* because I do not want to have to manually delete the return value).
What is the proper way (if any way exists) for an abstract class to return an instance of a concrete class derived from another abstract class?
Note I did see this solution: returning an abstract class from a function
but I do not want to make the return value static and loose thread safety.
Use smart pointers.
These are pointers deleted when not used anymore (see for example http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/smart_ptr.htm).
You can also return the object by value.
Some compilers provide the Return value optimization which optimize away the copy when returning an object.
Edit:
Sorry. I skimmed through the question and somehow missed the fact that inheritance is involved. Assuming that getBar() can return various kind of IBar returning an IBar pointer makes a lot of sense.
By returning a pointer to base the concrete object is kept intact. The slicing problem is avoided and the original vtbl pointer is available to make virtual function calls. Also (as you noted in your comment) returning an instance of an abstract class is just impossible.
Instead of returning a raw pointer I suggest you return a shared_ptr<IBar> to simplify memory management.
const shared_ptr<IBar> Foo::getBar()
{
shared_ptr<IBar> ret(new Bar());
return ret;
}
Then use it this way:
shared_ptr<IBar> pIBar(foo.getBar());
pIBar->myVirtualFunction();
shared_ptr is the most commonly used smart pointer type in C++0x. If you have a sufficiently recent compiler it will be in the std namespace. Older compiler may have it in the tr1 namespace and it's also part of boost.
You're returning a reference to a local variable. As soon as the function returns the reference, the stack gets popped and that Bar object ceases to exist.
EDIT: I didn't read the whole thing. You'll probably need to use a smart pointer.
Actually, is there any reason why you need to return a base class reference? You could avoid any smart pointer messiness by returning an object of the concrete type itself, since C++ allows covariant return types.
Since you want to transfer ownership of the returned object to the caller, the caller will have to destroy the object. In other words, returning IBar * is your best bet. If you are worried about having to manually call delete, you should look into using a smart pointer package, e.g. boost::shared_ptr.
If you don't want to take care of deletion then you have to use SmartPointers.
In C++ this is the only way to have object "deletes itself" when it is appropriated.
http://en.wikipedia.org/wiki/Smart_pointer
The object that has been created on the stack will be destructed when your stack is removed. The stack is removed when the function exits.
Instead, try something like this:
struct Foo : public IFoo
{
Bar m_Bar;
public:
virtual const IBar& getBar()
{
return m_Bar;
}
}