cocos-2dxメモリ管理
cppで実現されたcoco2d-xのメモリについて、cppの言語自身動的なメモリを自動的に開放できない。 auto_ptr、smart_ptrを使わず、object-cのようなaotoReleasePoolをcount referenceで実現しました。
count referenceをCCObject.hに関連定義
class CC_DLL Object
{
public:
/// object id, ScriptSupport need public _ID
unsigned int _ID;
/// Lua reference id
int _luaID;
protected:
/// count of references
unsigned int _referenceCount;
全てのクラスはCCObject(CCScene, CCSprite, CCLayerとか)をベースとして継承したクラスは、count referenceの仕組みがある。
autoreleaseをCCObject.cppに関連実現
Object* Object::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
呼び出すとCCObjectはPoolManagerに管理される。PoolManager実際の動作は、毎フレームの時ループでPoolにあるObjectをチェックした、reference数によって処理を行う。つまり、CCObjectのinstanceをnewした後、autoreleaseメッソドを呼び出すと、メモリを管理しなくていい。
CREATE_FUNCについて
実際使う時new initじゃなくてcreateを使う。CLASS.hによく使うCREATE_FUNCメソッドはCCPlatformMacros.hに定義した。
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
つまり、終期化した後、autoreleaseを使うこと。そして、createを使うとautoreleaseを呼ばなくていい。
retainについて
CCObject.hにretainを定義した。
inline void retain()
{
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
++_referenceCount;
}
それに対して、releaseメソッドは_referenceCountを減らす(0の時メモリを解放する)。
addChildについて
前話したautoreleasepoolについては、createしたinstance(背景かと、主人公とか)何もしない場合、次のフレームの時autoreleasepoolによるreleaseされる、エラーになる。その時CCNodeのaddChildメッソドを使う。名前通り、子供として追加すること。3つの形のaddhildがあるんですが、全てはChildrenのCCVectorにpushBackすること。
CCVector.h
void pushBack(T object)
{
CCASSERT(object != nullptr, "The object should not be nullptr");
_data.push_back( object );
object->retain();
}
中に object->retain()を使っている。それに対してpopBackにreleaseを使っている。要するに、addChildを使うと、
- ~parentのときは、ChildrenのCCVectorを削除する。つまりaddChildで追加したchildはparentが存在するchildも存在する(フレームに関係なく)
- 手動的にretain,releaseしなくていい、すでにparentが管理している
手動的にretainしたい場合
手動的のretainしたい場合もなる。永続かしたい、開発者がObjectのLift circleをコントロールしたい場合、手動的にretainを使う。retainを手動で呼ぶと、autoreleasepoolは削除できない(_referenceCountを0にできないから)、メモリリークを発生しまう。そして必ずpairとしてreleaseを使って、CCObjectのメモリをreleaseする。
まとめ
- new, initを避けてcreateを使う
- retainした後必ずrelease
- addChildを使ってretainを使わない場合、メモリを管理しなくていい(ただしremoveChildは必要)
メモとして、参考Cococs2dxバージョン:3.0.0betarsion: cocos2dx3.0-beta