当前位置:网站首页>201215-03-19 - cocos2dx memory management - specific explanation "recommended collection"
201215-03-19 - cocos2dx memory management - specific explanation "recommended collection"
2022-07-07 21:05:00 【Full stack programmer webmaster】
Hello everyone , I meet you again , I'm the king of the whole stack .
because cocos2dx Our use c++ Written , So memory management is just a trap , If you don't understand memory but business logic , What else are you playing c++, I watched this thing for a long time today , In fact, it is understood in essence , But there is a barrier that cannot be crossed , Finally, it was done tonight , So I want to share with you . Strive for me to put the high-quality essence of the Internet through my own understanding . Share it with you .
There are generally two ways to manage memory , Reference counting and garbage collection .
We cocos2dx Reference counting is used , And very hot java It's garbage collection . Reference count , Specific explanation of garbage collection :
Reference count : By maintaining a reference counter for each object , Record the number of times the object is currently referenced .
When an object adds a reference , Add one counter : And lose a quote , Counter minus one ; When count is 0 when . Marks the end of the life cycle of the object . Actively trigger the recycling and release of objects .
Reference counting solves the problem of object lifecycle management , But the problems of heap fragmentation and cumbersome management still exist . Garbage collection : He introduced his own active memory payback period , Try to completely liberate the program ape from the complex memory management task . He will actively track all references of each object , In order to find the object in use , Then there are real estate enterprises and objects that are no longer needed . Garbage collection period is usually executed as a separate low-level thread , Clear and recycle objects that have died or have not been used for a long time in the memory heap under unpredictable circumstances .
Let's focus on reference counting , Its principle is that we reference an object , Just add one to the reference count of the object , If you lose a reference and an object, reduce the reference count by one . stay cocos2dx The way is retain and release, Let's see CCObject. stay CCObject There's a property in it m_uReference Is the reference count .
CCObject::CCObject(void)<span style="white-space:pre"> </span>
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1 Note that there , Default this m_uReference yes 1 Of
, m_uAutoReleaseCount(0)
{
static unsigned int uObjectCount = 0;
m_uID = ++uObjectCount;
}
void CCObject::retain(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
++m_uReference;
}
retain Method , Each time will be m_uReference Add one
void CCObject::release(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
--m_uReference;
if (m_uReference == 0)
{
delete this;
}
}
release Each time will be m_uReference Minus one , And assume 0 Then delete fall .
Suppose we manage manually , Just use the above method .
But we mainly say that we actively manage , Taking the initiative to manage yourself is actually that you just work . We will hand over the issue of release to Cocos2dx Engine to release , There is no need for us to manually call release
Generally, there will be one in our class create Method . This method is probably like this
MyScene * MyScene::create()
{
MyScene *pRet = new MyScene;
if (pRet && pRet->init())
{
pRet->autorelease();<span style="white-space:pre"> </span>// Note that there , At this time, we give this object to the engine , We don't need to release manually again , Just wait for the engine to release itself
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
}
return NULL;
}
Some people will ask . You simply don't release because of such a sentence , It's up to the engine , How did you achieve . Is this thing reliable , Don't panic , Let's enter the method to see
CCObject* CCObject::autorelease(void)
{
CCPoolManager::sharedPoolManager()->addObject(this); // Let's go in again , See the following method
return this;
}
void CCPoolManager::addObject(CCObject* pObject)
{
getCurReleasePool()->addObject(pObject); // Let's go in again . See the following method
}
void CCAutoreleasePool::addObject(CCObject* pObject)
{
m_pManagedObjectArray->addObject(pObject); // Here suppose we continue to go down , Then we will eventually find one pObject.retain The method of ,
CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");
++(pObject->m_uAutoReleaseCount);
pObject->release(); // no ref count, in this case autorelease pool added.
}
First of all, we want to explain CCAutoreleasePool It is called self active release pool , stay CCPoolManager ( Actively release the pool management class by yourself ) We have a member variable in the class CCArray * m_pReleasePoolStack; This is to actively release the pool stack , Inside the store CCAutoreleasePool Example .
CCAutoreleasePool There's a CCArray * m_pManagedObjectArray, This is an internal array of objects .
In general, their relationship is like this . Every time we actively manage objects by ourselves , It will be added to the memory free pool , You might ask , We don't release this thing , When will it be released , The answer is to release every frame cycle . And create a self active release pool again .
Let's see mainLoop Code
void CCPoolManager::pop()
{
if (! m_pCurReleasePool)
{
return;
}
int nCount = m_pReleasePoolStack->count();
m_pCurReleasePool->clear(); // Look here, everyone . This means that the memory pool is empty , We should see how he empties
if(nCount > 1)
{
m_pReleasePoolStack->removeObjectAtIndex(nCount-1);
// if(nCount > 1)
// {
// m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);
// return;
// }
m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);// Here we initialize the memory pool again in a new frame
}
/*m_pCurReleasePool = NULL;*/
}
void CCAutoreleasePool::clear()
{
if(m_pManagedObjectArray->count() > 0)
{
//CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
int nIndex = m_pManagedObjectArray->count() - 1;
#endif
CCObject* pObj = NULL;
CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)
{
if(!pObj)
break;
--(pObj->m_uAutoReleaseCount);// This means that the sign of self active management becomes 0 了
//(*it)->release();
//delete (*it);
#ifdef _DEBUG
nIndex--;
#endif
}
m_pManagedObjectArray->removeAllObjects();
}
}
It's probably like this , We imagine assuming that we are simply create A manager , I didn't hang it on the rendering tree , Our citation count must be 1 ah , And then through the reduction of their own active release pool . Will be released .
Case one :
CCScene *pscene = CCScene::create(); // The reference count is 1, Default internally autorelease 了
.
.
. After the frame cycle, the stack is cleared , Quote minus one ,pscene He was killed .
Another situation :
CCScene *pscene = CCScene::create(); // The reference count is 1. Default internally autorelease 了
addChild(pscene);// The reference count is 2.
.
.
.
After a frame cycle of stack clearing , Quote minus one . The reference count becomes 1. And next time, I won't actively release myself into the pool . So this spirit can always be on the rendering tree , When do we want to delete him . Maybe you want to release this “ spirit ”, We still need to call it manually release. Or call it autorelease Method .
Let me make a summary , Well, that's it , Let's have one CCObject It's running autorelease Method , The active release pool will be given to us by default at the beginning of the next frame cycle -1, Because we managed . Theoretically , Suppose the reference count is zero after subtracting one , It is what we should release , But we trust the engine , The engine will be duty bound to help us release it .
Suppose we not only created it ourselves , It is also added to the rendering tree . It means that we will continue to use this spirit , If you actively release the pool, you will reduce the reference count by one to one , The engine will know that you are creat You are still using this spirit , I don't care , Keep him alive , I still have to clean up my active release pool . Because I want to prepare for this frame cycle .
I unconsciously wrote this point . Originally, I still wanted to say a little more , Brush your teeth and go to bed early , Today, this really makes my day dark . The sun gave forth no more of its light , I understand . I just didn't convert my thoughts , At first, I didn't understand why I was so released , Later I learned . We should have done this . But sometimes these are registration functions , Interrupt function and so on , We don't know when to do , So let the engine do it , Because he knows how to do .
Brush one's teeth , sleep , Good night, everyone .......
.
.
Publisher : Full stack programmer stack length , Reprint please indicate the source :https://javaforall.cn/116441.html Link to the original text :https://javaforall.cn
边栏推荐
- Make this crmeb single merchant wechat mall system popular, so easy to use!
- 2022年在启牛开中银股票的账户安全吗?
- Codeforces round 275 (Div. 2) C – diverse permutation (construction) [easy to understand]
- 恶魔奶爸 A0 英文零基础的自我提升路
- Airiot helps the urban pipe gallery project, and smart IOT guards the lifeline of the city
- 如何满足医疗设备对安全性和保密性的双重需求?
- 嵌入式系统真正安全了吗?[ OneSpin如何为开发团队全面解决IC完整性问题 ]
- I wrote a markdown command line gadget, hoping to improve the efficiency of sending documents by garden friends!
- easyui 日期控件清空值
- ISO 26262 - 基于需求测试以外的考虑因素
猜你喜欢
Is embedded system really safe? [how does onespin comprehensively solve the IC integrity problem for the development team]
H3C s7000/s7500e/10500 series post stack BFD detection configuration method
How does codesonar help UAVs find software defects?
ERROR: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your
万字总结数据存储,三大知识点
How to meet the dual needs of security and confidentiality of medical devices?
Helix QAC 2020.2新版静态测试工具,最大限度扩展了标准合规性的覆盖范围
【C语言】指针进阶---指针你真的学懂了吗?
How to meet the dual needs of security and confidentiality of medical devices?
最新版本的CodeSonar改进了功能安全性,支持MISRA,C ++解析和可视化
随机推荐
Optimization cases of complex factor calculation: deep imbalance, buying and selling pressure index, volatility calculation
论文解读(ValidUtil)《Rethinking the Setting of Semi-supervised Learning on Graphs》
国家正规的股票交易app有哪些?使用安不安全
嵌入式系统真正安全了吗?[ OneSpin如何为开发团队全面解决IC完整性问题 ]
Feature generation
Nebula importer data import practice
Codeforces 474 F. Ant colony
Ubuntu安装mysql8遇到的问题以及详细安装过程
使用高斯Redis实现二级索引
Implementation of mahout Pearson correlation
微服务远程Debug,Nocalhost + Rainbond微服务开发第二弹
数值法求解最优控制问题(〇)——定义
gridView自己定义做时间排版「建议收藏」
Alibaba cloud award winning experience: how to mount NAS file system through ECS
Small guide for rapid formation of manipulator (12): inverse kinematics analysis
CodeSonar网络研讨会
Tensorflow2. How to run under x 1 Code of X
Cocos2d-x game archive [easy to understand]
Word inversion implements "suggestions collection"
上海交大最新《标签高效深度分割》研究进展综述,全面阐述无监督、粗监督、不完全监督和噪声监督的深度分割方法