cocos2dx CCHttpRequest里面的内存引用计数的故事

CCHttpRequest 本身是一个CCObject 对象, 用于lua的create函数 默认会retain request对象一次,因此需要在lua的callback函数里面处理结束request之后,需要release对象否则会内存泄露。

实际的引用计数变化的过程如下:

new  引用计数 = 1

autorelease 引用计数先变成2 再变成1 , 将对象加入自动释放池子里面之后,对象引用计数会+1, 接着会调用对象的release方法,对象引用计数又减去1

retain 引用计数变成 2

start 开始http请求,对象加入schedule 的列表里面 引用计数+1 引用计数变成3

update 过程中,到下一个update循环的时候,对象的引用计数会减去1,因为自动释放池子release了这个对象,这时候引用计数变成2

http请求处理结束,update函数里面检测结束,取消schedule 更新,但是因为当前在函数体内,所以不会立即release掉request对象,而是等待本次回合结束的时候再release对象

http请求结束,在callback函数里面release 掉对象,引用计数-1  变成 1

在本次更新回合结束,schedule模块,将标记删除的对象的引用计数-1, 引用计数 = 0 对象被删除掉。



#include "network/CCHttpRequest.h"#include "network/CCHttpRequest_impl.h"#include "cocos2d.h"#include "CCLuaEngine.h"using namespace cocos2d;NS_CC_EXT_BEGINCCHttpRequest* CCHttpRequest::createWithUrl(CCHttpRequestDelegate* delegate,                                            const char* url,                                            CCHttpRequestMethod method,                                            bool isAutoReleaseOnFinish){    CCHttpRequest* request = new CCHttpRequest(delegate, url, method, isAutoReleaseOnFinish);    request->initHttpRequest();    request->autorelease();    if (isAutoReleaseOnFinish)    {        request->retain();    }    return request;}CCHttpRequest* CCHttpRequest::createWithUrlLua(int nHandler, const char* url, bool isGet){    CCHttpRequest* request = new CCHttpRequest(NULL, url, isGet?CCHttpRequestMethodGET:CCHttpRequestMethodPOST, true);    request->m_luaHandler = nHandler;    request->initHttpRequest();    request->autorelease();    request->retain();    CCLog("request count is? %d", request->retainCount());    return request;}bool CCHttpRequest::initHttpRequest(void){    m_request = new CCHttpRequest_impl(m_url.c_str(), m_method);    return true;}CCHttpRequest::~CCHttpRequest(void){    delete (CCHttpRequest_impl*)m_request;}void CCHttpRequest::addRequestHeader(const char* key, const char* value){    if (key && value)    {        ((CCHttpRequest_impl*)m_request)->addRequestHeader(key, value);    }}void CCHttpRequest::addPostValue(const char* key, const char* value){    if (key && value)    {        ((CCHttpRequest_impl*)m_request)->addPostValue(key, value);    }}void CCHttpRequest::setPostData(const char* data){    if (data)    {        ((CCHttpRequest_impl*)m_request)->setPostData(data);    }}void CCHttpRequest::setTimeout(float timeout){    ((CCHttpRequest_impl*)m_request)->setTimeout(timeout);}bool CCHttpRequest::getIsInProgress(void){    return ((CCHttpRequest_impl*)m_request)->getIsInProgress();}void CCHttpRequest::start(bool isCached){    CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);    if (((CCHttpRequest_impl*)m_request)->start())    {        CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this, 0, false);    }}void CCHttpRequest::cancel(void){    CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);    ((CCHttpRequest_impl*)m_request)->cancel();}void CCHttpRequest::clearDelegatesAndCancel(void){    m_delegate = NULL;    cancel();}int CCHttpRequest::getResponseStatusCode(void) {    return ((CCHttpRequest_impl*)m_request)->getResponseStatusCode();}const char* CCHttpRequest::getResponseString(void){    return ((CCHttpRequest_impl*)m_request)->getResposeString().c_str();}const void* CCHttpRequest::getResponseData(int* dataLength){    return ((CCHttpRequest_impl*)m_request)->getResponseData();}int CCHttpRequest::getResponseDataLength(){    return ((CCHttpRequest_impl*)m_request)->getResponseDataLength();}CCHttpRequestError  CCHttpRequest::getErrorCode(void){    return ((CCHttpRequest_impl*)m_request)->getErrorCode();}const char* CCHttpRequest::getErrorMessage(void){    return ((CCHttpRequest_impl*)m_request)->getErrorMessage();}void CCHttpRequest::update(float dt){    CCLog("update Request state %d", retainCount());    CCHttpRequest_impl* request = (CCHttpRequest_impl*)m_request;    if (!request || !request->getIsInProgress())    {        CCDirector::sharedDirector()->getScheduler()->unscheduleUpdateForTarget(this);    }        if (request->getIsCompleted())    {        if (m_delegate) m_delegate->requestFinished(this);                if (m_luaHandler)        {bool isSuc = (request->getErrorCode()==CCHttpRequestErrorNone);CCLuaEngine* engine = CCLuaEngine::defaultEngine();engine->getLuaStack()->clean();engine->getLuaStack()->pushBoolean(isSuc);engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);            CCLog("afterHandler retainCount %d", retainCount());/*            cocos2d::CCLuaValueDict dict;            dict["name"] = cocos2d::CCLuaValue::stringValue("completed");            dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");            cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();            engine->cleanStack();            engine->pushCCLuaValueDict(dict);            engine->executeFunctionByHandler(m_luaHandler, 1);*/        }            }    else if (request->getIsCancelled())    {        if (m_delegate) m_delegate->requestFailed(this);                if (m_luaHandler)        {CCLuaEngine* engine = CCLuaEngine::defaultEngine();engine->getLuaStack()->clean();engine->getLuaStack()->pushBoolean(false);engine->getLuaStack()->executeFunctionByHandler(m_luaHandler, 1);/*            cocos2d::CCLuaValueDict dict;            dict["name"] = cocos2d::CCLuaValue::stringValue("failed");            dict["request"] = cocos2d::CCLuaValue::ccobjectValue(this, "CCHttpRequest");            cocos2d::CCLuaEngine* engine = cocos2d::CCLuaEngine::defaultEngine();            engine->cleanStack();            engine->pushCCLuaValueDict(dict);            engine->executeFunctionByHandler(m_luaHandler, 1);*/        }    }}NS_CC_EXT_END


原文地址:https://www.cnblogs.com/liyonghelpme/p/4273739.html