_listView->removeAllItems() MEMORY LEAK

Hi all,

When I call (cocos2d::ui::Listview) _listView->removeAllItems() method , why all items of listview not released ? As you can see the output below, the ReferenceCount of all items is not decreased and the items is not released ! Is this a bug ?

Here is my code :

	std::vector<Widget*> stdList;

    for (int i = 0; i < _totalCount; ++i) {
        if (i < _spawnCount) {
            Widget* item = default_item->clone();
            item->setTag(i);
            Button* btn = (Button*)item->getChildByName("Title Button");
            btn->setTitleText(_array.at(i));
			stdList.push_back(btn);
			CCLOG("XXX BeFore btnRefC:%d ", btn->getReferenceCount());

            _listView->pushBackCustomItem(item);

			CCLOG("XXX After btnRefC:%d ", btn->getReferenceCount());
        }
    }

	_listView->removeAllItems();

	for (size_t i = 0; i < stdList.size(); i++)
	{
		if (auto object = stdList.at(i))
		{
			CCLOG("object RefC:%d ", object->getReferenceCount());
		}
	}

And here is the output

XXX BeFore btnRefC:2 
XXX After btnRefC:2 
XXX BeFore btnRefC:2 
XXX After btnRefC:2 
XXX BeFore btnRefC:2 
XXX After btnRefC:2 
XXX BeFore btnRefC:2 
XXX After btnRefC:2 
XXX BeFore btnRefC:2 
XXX After btnRefC:2 
object RefC:2 
object RefC:2 
object RefC:2 
object RefC:2 
object RefC:2

Could someone help me explain about this issue ? Thanks !

this feels like a but, did you create a GitHub issue for it yet?

@dragon0962 What you have shown may not be a memory leak.

I’m guessing that the code you posted is all within the same function, or at least runs within a single update loop.

Here is what is happening:

  1. You’ve created a Widget, being default_item, and default_item contains a node of type Button.
  2. You clone default_item, and at this point, item has a reference count of 1, and btn has a reference count of 2. The reason is that it’s an auto-release object, so on creation it is 1, then on adding it to the clone of the default_item, it becomes 2, and you can see that in your CCLOG("XXX After btnRefC:%d ", btn->getReferenceCount()); statement. There was no reason to add 2 of those CCLOG statements before and after pushBackCustomItem(), since that only affects the ref count of the item, not its child nodes.
  3. Next is the call to removeAllItems. That’s all well and good, but you have to remember that all the items are auto-release items, meaning they haven’t actually been released yet by the object pool code since we’re still in the same single update call. This would mean the items would now go from a ref count of 2 to 1, and their child nodes, the buttons, are still unaffected, and would still be a refcount of 2.
  4. If you wait till the next update loop, the auto-release pool would have cleared, so all references counts would have reduced by 1. In this case, items go to 0, so they’ll be freed, and because of this, their children are also reduced by 1, so the button node now has a ref count of 1. Since the button is also in the auto-release pool, and it’s still running at this point, then button is auto-released, so its ref count goes to 0, and it is freed.

That’s my understanding of how this is all working, and doing a quick test in my app shows that this is how it seems to work.

3 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.