关于cocos2d 3.x对象内存管理疑问
问题:cocos2d 3.x当调用removeFromeParent后其子节点内存什么时候会被释放?
楼主版本,3.2
下面是楼主找到与内存相关源码与对源码的分析,求指导,求解惑!!!
1.一般create方法都会调用这个函数,将对象加入自动回收池
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
2.主循环中会调用回收池的clear函数,这个函数之后,回收池不再有对象,即若对象引用计数为1,则直接被干掉,如果引用计数大于1,则对象内存交由调用了retain方管理,与回收池不再有关系
void DisplayLinkDirector::mainLoop()
{
if (_purgeDirectorInNextLoop)
{
_purgeDirectorInNextLoop = false;
purgeDirector();
}
else if (! _invalid)
{
drawScene();
// release the objects
PoolManager::getInstance()->getCurrentPool()->clear();
}
}
void AutoreleasePool::clear()
{
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
_isClearing = true;
#endif
for (const auto &obj : _managedObjectArray)
{
obj->release();
}
_managedObjectArray.clear();
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
_isClearing = false;
#endif
}
3.对象删除,下面三个函数源码,detachChild为removeFromeParent调用,用于将child删除,可以看见在_children.erase(childIndex);这个函数中,会调用child的release函数,释放掉child内存,但是没有见到有便利删除child的子节点的代码,我以为会在析构函数中做,但是析构中只是做了遍历子节点,将其parent指针置空而已,并未发现有循环调用release
void Node::detachChild(Node *child, ssize_t childIndex, bool doCleanup)
{
// IMPORTANT:
// -1st do onExit
// -2nd cleanup
if (_running)
{
child->onExitTransitionDidStart();
child->onExit();
}
#if CC_USE_PHYSICS
if (child->_physicsBody != nullptr)
{
child->_physicsBody->removeFromWorld();
}
#endif
// If you don't do cleanup, the child's actions will not get removed and the
// its scheduledSelectors_ dict will not get released!
if (doCleanup)
{
child->cleanup();
}
// set parent nil at the end
child->setParent(nullptr);
_children.erase(childIndex);
}
iterator erase(ssize_t index)
{
CCASSERT(!_data.empty() && index >=0 && index < size(), “Invalid index!”);
auto it = std::next( begin(), index );
(*it)->release();
return _data.erase(it);
}
Node::~Node()
{
CCLOGINFO( “deallocing Node: %p - tag: %i”, this, _tag );
#if CC_ENABLE_SCRIPT_BINDING
if (_updateScriptHandler)
{
ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptHandler(_updateScriptHandler);
}
#endif
// User object has to be released before others, since userObject may have a weak reference of this node
// It may invoke `node->stopAllAction();` while `_actionManager` is null if the next line is after `CC_SAFE_RELEASE_NULL(_actionManager)`.
CC_SAFE_RELEASE_NULL(_userObject);
// attributes
CC_SAFE_RELEASE_NULL(_glProgramState);
for (auto& child : _children)
{
child->_parent = nullptr;
}
removeAllComponents();
CC_SAFE_DELETE(_componentContainer);
#if CC_USE_PHYSICS
setPhysicsBody(nullptr);
#endif
CC_SAFE_RELEASE_NULL(_actionManager);
CC_SAFE_RELEASE_NULL(_scheduler);
_eventDispatcher->removeEventListenersForTarget(this);
#if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS && COCOS2D_DEBUG > 0
_eventDispatcher->debugCheckNodeHasNoEventListenersOnDestruction(this);
#endif
CCASSERT(!_running, "Node still marked as running on node destruction! Was base class onExit() called in derived class onExit() implementations?");
CC_SAFE_RELEASE(_eventDispatcher);
}