is it possible to use c++11 smart pointers with nodes user data? has anyone tried it before?
node->setUserData(void* usrData);
node->getUserData();
Solved:
i figured a way to store objects in a Node without having to delete theme manually(gets automatically deleted when the Node is destroyed) and it might not be the best solution but it is a solution nevertheless, it involves inheriting from cocos2d::Ref class and using nodes setUserObject(Ref* ptr)!
this is how i made it happen:
1)- make a class/struct that inherits from cocos2d::Ref class.
2)- fill it with your custom properties and methods.
3)- make sure the object calls autorelease().
struct Box : public cocos2d::Ref
{
// some properties here
Box() {
//autorelease means let other Nodes retain and release this object.
//if you don't call autorelease then the object destructor won't get called which means in turn object memory is not released.
this->autorelease();
}
~Box() {
//just to check if the object destructor is called or not.
log("=========================");
log("Box is destroyed");
log("=========================");
}
};
4)- make an object instance and put its pointer in any Node UserObject like this:
auto box = new Box;
this->setUserObject(box);// am putting it in the Layer UserObject
now the box object will be destroyed automatically whenever the Layer/Node is destroyed (no delete is needed)
PS: you should properly exit the cocos2d-x app in order for the nodes(Node, Layer, Scene) destructors to be called so can nodes children be destructed properly(children destructors are called) ... just press the back button if your in an emulator or use a close button that calls Director::end().
This was a comment, but got too long.
I wouldn't see it as hopeless as #Joachim Pileborg does in the comments (although his points are true in principle). The only thing you have to assume is that setUserData is only observing, i.e. it performs no memory-related actions and particularly no delete.
You can then either simply use a smart pointer "outside",
auto ptr = std::make_unique<some_object>();
node->setUserData(ptr.get());
Now, if the program then exits in a proper way, at least you don't have to manually delete ptr. But, as mentioned by Joachim, of course you have to make sure that ptr lives as long as it is might be used inside node.
Alternatively, you can write small wrapper around the node class which contains a shared_ptr<void> ptr variable and which offers a setUserData(shared_ptr<void>) method. If this method is invoked, it first copies the shared pointer and internally calls node->setUserData(ptr.get()) method. Then the underlying object is guaranteed to stay alive.
Related
Edit
I suppose the code below would assume I have an overloaded version of addChild() that accepts a Sprite already wrapped in a unique_ptr, where taking ownership would be fine. Just thought I'd mention that before someone else did. :) . I made up all the code here after a very long day, so please take it as pseudo code quality meant only to demonstrate the issue at hand.
Original Question
I'm writing a framework where there is a display list, parents/children etc. I'm thinking that using unique_ptr<Sprite> for example is the way to go here, since when you add a child to a parent display object, it's only logical that the parent now becomes the sole owner of that child.
However, there will be methods available such as getChildAt(index) and getChildByName, etc, which I believe should return a reference or pointer value, since these methods are simply meant to expose a child to operations, not transfer ownership.
Finally, the issue and the reason for this question, is in the following situation. Lets assume we have two Sprite objects which are children of the root of display list, Stage. Let's say we have a third child Sprite.
Stage newStage;
std::unique_ptr<Sprite> parentOne(new Sprite);
std::unique_ptr<Sprite> parentTwo(new Sprite);
newStage.addChild(parentOne); //Stage takes ownership of parentOne
newStage.addChild(parentTwo); //Stage takes ownership of parentTwo
std::unique_ptr<Sprite> someChild(new Sprite);
parentOne->addChild(someChild) //parentOne takes ownership of someChild.
Now, somewhere else lets say in the code base of the game or whatever using this framework, someChild is accessed via getChildAt(int index);.
Sprite& child = parentOne->getChildAt(0);
It would be perfectly legal for the following to then happen.
parentTwo->addChild(child);
The addChild method handles removing the child from it's previous parent, if a parent exists, so that the new parent can now make this child part of its section of the display list.
I'm returning the child(ren) from each sprite as a reference or pointer, because we don't want to hand off ownership (in methods such as getChildAt()), just provide access to the child. We don't want to hand it off as a unique_ptr and have it fall out of scope and die.
However, as I say, it would be perfectly legal and normal for this child (now accessed by a reference or pointer) to be passed off to another container (lets say in a drag and drop operation, dragging an item from one list to another). The problem we have now is that the unique ownership needs to be transferred from one parent to another, but we only have a reference or raw pointer.
I'm wondering what a sane solution to this problem would be. If I return a pointer, is it possible to transfer the ownership correctly at this stage?
void Sprite::addChild(Sprite* newChildToOwn)
{
/* by checking newChildToOwn->parent we can see that the child is already owned
by someone else. We need to not only remove the child from that parents' part of the
display list and add it here, but transfer exclusive object ownership of newChildToOwn
to this->.
*/
}
The release method gets you the pointer to the object and releases it from the unique_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr/release
For your structure, you should probably have method called releaseChild(index) that handles you the ownership by returning pointer.
To transfer ownership you need to have access to the unique_ptr as the raw pointer knows nothing of how it is being used.
Would it work to have the remove child method return the unique_ptr so that the object is kept alive during the transfer and the Sprite will be able to take the ownership? This will allow references to be used in other places as you have already.
I'm reading around the web and the documentation but to be honest, I don't get it. Since I'm new to cocos2d-x I would like to understand better how the objects are created/retained and what I'm supposed to do to release them (if required). The thing that confuses me is the usage of smart pointers that I don't know very well.
Imagine that in my CCLayer (added to the CCScene) I add a CCSprite, so i do:
this->sprite = CCSprite::create("mySprite.png");
this->addChild(sprite);
then since I've used create() I'm supposed to release it somewhere? in the destructor of the CCLayer maybe? or I have nothing to do about that?
I know the basics of C++ so if I do "new" an object I actually have to delete it in the destructor or when I don't need it anymore, but what about the cocos2dx objects?
Here is the thing,
Object of the class Ref or any class derived from it has a variable _retainCount which represents the scope of the object.
Also there is an autorelease pool which is similar to the garbage collector in java. The object which is added to this autorelease pool will be deleted at the end of the frame. Unless its _retainCount!=0
Now when you create new object of Ref or derived class using the create method it is already added to the autorelease pool and you don't need to release it or delete it anywhere. As you can see in the create function of Node below.
Node * Node::create()
{
Node * ret = new (std::nothrow) Node();
if (ret && ret->init())
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}
But when you create new object using 'new' you definitely need to delete it after its use is over. Though it is not recommended to use New to allocate the objects of cocos2d classes. Rather use create.
Node* temp=Node::create();
then,
temp->retain();
//your work...
temp->release();
or
Node* temp=Node::create();
Node* tempChild=Node::create();
temp->addChild(tempChild);
//your work...
temp->removeFromParent();
Second thing,
when your object is added to the autorelease pool but you need to increase its scope you could just retain it , this increments its retain count by one and then you have to manually release it i.e, decrement its retain count after its use is over.
Third Thing,
Whenever you add child your object it is retained automatically but you don't need to release it rather you remove it from the parent as mentioned above.
Official documentation is #link below.
[http://www.cocos2d-x.org/wiki/Reference_Count_and_AutoReleasePool_in_Cocos2d-x#Refrelease-retain-and-autorelease][1]
Sorry,my English is poor!
1.The this->sprite will be auto release when CCLayer destroy if you call CCSprite::create(...); and addChild(...); .
2.if you want remove this->sprite sometimes ,you could call this:
this->sprite->removeFormParents();
this->sprite=NULL;
Cocos2d-x uses objective-c-like memory management system, so that variables have retain count. With each cocos main-loop pass objects' retain count decrements and when it reaches 1 it's released. CCObject containing another objects keep them alive by incrementing their retain count. So that CCObjects retains themselves and usually you don't need to worry about memory management. However, there are situations in witch you'd want to turn autorelease off and manually manage the CCObjects' lifetime with retain() and release().
There are some common situations with cocos2d-x leading to memory leaks such as having a CCObject contacting another CCObject that keep the first one alive using setUserObject(). Thus, both will never be destroyed.
So, in general, in most cases it is the best to stick with built-in autorealse model and manually managing some edge cases, that'd normally lead to memory leaks. Also, keep in mind that there are opposite situations - f.e. accessing a dead ccobject can lead to runtime error.
Offtopic: you don't have to write this when accessing member/method.
I've been lurking about these questions for awhile and learned alot but recently have come up against a problem that I don't understand. I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel). I've defined the object using the new keyword. Thus in the header I have
QMovie * movie;
For simplicity I'll put the equivalent code in a single method. This is equivalent to the two lines of code
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
This works (I don't know why) but since it is a repeated operation I worry about memory leaks. It appears that the second definition replaces the first one successfully but since presumably they each have diffeent pointers I don't know how to delete the pointer to the first definition. I delete movie in the class destructor but don't know if it will delete everything. Anyone know what is happening here?
P.S. I do this because the only way (I've found in Qt) to create a QMovie object using data in a QByteArray (which was downloaded from the web) is to use the QMovie constructor. If I just wanted to replace the current movie data with new data from a file I could use the method
movie->setFileName(fileName);
but this isn't an option when using binary data. Note: QMovie also has a constructor that has a filename instead of a QByteArray as an argument. Using filenames also works using the above code and is easier to test.
Any help will be appreciated.
Generally speaking, if anything derived from QObject is contained in a hierarchy of QObjects, they are automatically destructed when the parent is destructed. In your case, you are giving the QMovie a parent through the constructor, so the cleanup should be taken care of for you. If you want to confirm, derive a class from QMovie, implement a destructor that prints a message, and make sure it is called when you expect (i.e. when the parent is destructed).
The idiomatic way of doing it in C would be:
Initialize the pointer to zero.
Before assigning to it, free() the object pointed to by the old pointer. You do not need to check for zero: free() on a zero pointer is a safe no-op.
free() the object when the pointer goes out of scope.
The idiomatic way of doing it in Qt is even simpler.
Use QSharedPointer<> or QScopedPointer<>. It will automatically delete the pointed-to object when it goes out of scope.
If only one pointer is supposed to own the object, use QScopedPointer. It will delete the pointed-to object when it goes out of scope. This is similar to std::auto_ptr.
For shared ownership, use QSharedPointer. It will delete the pointed-to object when the last QSharedPointer that points to it goes out of scope/gets destroyed.
For QScopedPointer, use reset(T*other) method to assign a new value to the pointer. For QSharedPointer, you can only assign other shared pointers to it, like QSharedPointer a = QSharedPointer(new Class);
In either case, any previously pointed-to object will be deleted.
Thus:
class MyClass {
QScopedPointer<QMovie> movie1;
QSharedPointer<QMovie> movie2;
public:
MyClass {} // note: no need for any special initialization
void method() {
movie1.reset(new QMovie(...));
movie2 = QSharedPointer(new QMovie(...));
}
};
This is completely safe. You can call MyClass::method() as often as you wish with no memory leaks. At any point in time, MyClass will keep alive at most two QMovie objects.
QMovie * movie = new QMovie(QByteArray1,this);
QMovie * movie = new QMovie(QByteArray2,this);
If these two lines are in the same .cc file, then you will get a redefinition error. If the two lines are in separate .cc files, then when you build the executable, you will get a multiple definition error. But, your question has this wording:
I'm using Qt and need to create/replace a QMovie object in various class methods (which is ultimately set in a QLabel)
If the QMovie object resides in different classes, you don't have a memory leak, because each class's pointer is different from another's.
However, if your intention is that all the classes refer to the same QMovie instance, you will need to find a way to pass the instance to each object. Alternatively, you would have them all refer to the same one (i.e., using the singleton pattern).
I have two four classes:
MainClass (class where things start)
XmlReader (class used to parse an xml file)
SerialPortSettings (holds info about the serial port read from the xml-file, e.g. baud rate, comport etc)
SerialPortListener (takes a reference to a SerialPortSettings object in its constructor)
MainClass has a method to read things from an xml-file.
In this method, it first creates an instance of XmlReader and gives it an xml-file as a constructor parameter. This xmlReader does only need to exist within this method:
XmlReader xmlReader (xmlFile);
The xmlReader parsers the xmlFile. MainClass gets access the xml-stuff by calling get-methods in XmlReader. So far everything is good.
However, one of the methods XmlReader offers, is a method which creates an object of type SerialPortSettings based on the information read from the xml-file:
SerialPortSettings* XmlReader::getSerialPortSettings() {
.... // reading stuff from xml file
return new SerialPortSettings(baudRate, dataBits, comport);
}
This method is called from MainClass and the return value is stored in a pointer:
SerialPortSettings* settings = xmlReader.getSerialPortSettings();
The next thing the MainClass does is to create a SerialPortListener (which is a member-variable that has to exist until MainClass is exited). SerialPortListener takes a reference to a SerialPortSettings in it's constructor:
m_serialPortListener = new SerialPortListener(*settings);
Hence SerialPortSettings also has to exist until MainClass exits, therefore I have created this as a pointer.
So here is the clue:
In the SerialPortListener destructor I tried to delete the SerialPortSettings-object:
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
Then in the MainClass destructor I deleted the SerialPortListener-object:
MainClass::~MainClass() {
delete m_serialPortListener;
}
This fails. I get an error saying that I deleted something twice in the main-class:
*** glibc detected *** ./ioserver: double free or corruption (out): 0x00860d80 ***
When I remove the delete &m_settings from SerialPortListener, it works fine.
But when should pointer be deleted? What is the correct thing to do? I really want my xml-reader to create the SerialPortSettings - object, insted of returning all of the info (baud rate, comport etc) to MainClass and create the SerialPortSettings object itself.
A good solution is to simply let xmlReader::getSerialPortSettings return a SerialPortSettings by value.
Let the compiler do the optimization.
But where you do need to handle pointer lifetimes, do use smart pointers, such as std::auto_ptr or boost::shared_ptr. The key idea is to define ownership. The owner (which in the case of boost::shared_ptr is the collection of smart pointers referring to the object) is responsible for deleting – no-one else.
Cheers & hth.,
The pointer should be deleted at the end of MainClass.
It makes no sense (to me, at least) to use delete on a reference.
It would be way cleaner to not have the XML reader create new objects; treat SerialPortSettings as a "dumb" container, and just pass in a reference to fill in with data from the XML:
XmlReader::getSerialPortSettings(SerialPortSettings& settings);
the actual instance can then be a local variable in the main program, and be passed (by const reference, this time) to the serial port when it's created:
SerialPortSettings portSettings;
m_xmlReader->getSerialPortSettings(portSettings);
m_serialPort = new SerialPort(portSettings);
the life time of the settings instance is then naturally the same as the scope it's in, since it's just a local variable.
If the method in the main class that reads XML needs to exit before the serial port goes out of scope, you could make the settings a member variable of the main class, instead.
What is the datatype of m_settings? Is it a SerialPortSettings* or a SerialPortSettings? If the latter, you can't delete it like that anyway, as it's allocated on the stack. If it's the former (a pointer), you do not need the reference operator. Simply write delete m_settings;
A simple typo in your delete:
delete &m_settings;
should be:
delete m_settings;
For any pointer you should decide who owns the pointer, and that should be who deletes it.
Or you can use a smart pointer such as shared_ptr and eliminate the problem altogether.
SerialPortListener::~SerialPortListener() {
delete &m_settings;
}
That block looks quite weird. Are you sure you aren't trying to delete value by reference? Cause C++ does it automatically when you delete the class, so your delete is really trying to delete twice.
OK, first of all, you're missing the truly important bit of information which is HOW is SerialPortListener::m_settings being stored. Because of the error you're getting, I'm guessing you're actually storing a copy of it, which means: I bet you have something like this:
class SerialPortListener {
SerialPortSettings m_settings;
SerialPortListener(SerialPortSettings set) {
m_settings = set;
}
}
if it's something similar to this, then the listener is saving a copy of the object in it's own memory, and deleting it doesn't make sense, since it's not a pointer. Rule of thumb, never do delete &anything until you know what you're doing and realize you really need to.
In terms of "correctness", the pointer should be freed by the main class, since it was who created it. Or if you don't have any use for it in the main class, and want the listener to delete it, save a pointer instead of an object or reference in the listener.
I ended up making m_serialPortSettings a pointer in SerialPortListener, and deleting it from there.
I currently have something similar to the following:
class Parent
{
//just a single child... for sake of simplicity
//no other class holds a shared_ptr reference to child
shared_ptr<Child> _child;
System * getSystem() {...}
}
class Child
{
weak_ptr<Parent> _parent;
~Child
{
_parent.lock()->getSystem()->blah();
}
}
The Child destructor always crashes, since when ~Child() runs _parent is always expired. Is there a typical solution to this weirdness?
In short, is there a way to not destroy _parent until ~Child finishes?
Since by the time the destructor for the the child gets called, the parent's destructor has already run (dtors for member objects get run after the dtor for the containing object), even if the child was holding a plain pointer to the parent, calling the parent's member function would be invalid by the time ~Child() was called.
You might be able to work around this by having Child call getSystem() at some earlier point and cache the result. Maybe in the constructor of Child (if it has a reference to the parent at the time) or maybe there can be an interface added so that Parent can let the child know it needs to collect whatever it might need during destruction from the parent at that time.
I understand that neither of these is a great solution (it increases coupling of the objects) -hopefully someone will post a better option.
Removing the circular reference is preferable, but if you cannot you can force Child to be destroyed before Parent is completely gone. In the destructor, explicitly call reset() on Child. This will force it to be destroyed immediately, assuming there are no other shared_ptrs to it.
Warning, if Parent is actually a base class all of it's subclasses will alreayd have been destroyed. Virtual function calls will probably not behave as expected.
First rule of weak_ptr: always check the locking (returned pointer or exception): after all the real reason to use weak_ptr is that it doesn't control the life-cycle of the pointed object.
_parent.lock()->
Here you assume that lock will succeed, IOW that your weak_ptr will not have expired at that time.
So, you should not be using a weak_ptr at all, but a shared_ptr instead.
Things will be much more clear if you do not misuse weak_ptr. You will see that you have two objects that try to manage each other lifetime, and that your design needs to be fixed. (Throwing weak_ptr into the mix does not fix a design.)
Just from the code you posted this should work. The only thing deleting _child is the parent class.
So there are two possibilites: First, something else also has a reference to the _child pointer, and keeps it ref count alive, and then parent is destroyed. Then eventually whatever else is holding onto child is also destroyed, killing off the child then.
Scenario 2 is that the call to getSystem depends on some other members youre not showing us, and those are getting deleted before the _child shared_ptr is.