fixed #1335: Memory leaks in cocos2dx and CCBReader.

This commit is contained in:
James Chen 2012-06-19 16:31:26 +08:00
parent c1883c1237
commit 591566b43a
21 changed files with 362 additions and 294 deletions

View File

@ -5,12 +5,17 @@
NS_CC_EXT_BEGIN
#define CCB_MEMBERVARIABLEASSIGNER_GLUE(TARGET, MEMBERVARIABLENAME, MEMBERVARIABLETYPE, MEMBERVARIABLE) if(pTarget == TARGET && pMemberVariableName->compare(MEMBERVARIABLENAME) == 0) { \
#define CCB_MEMBERVARIABLEASSIGNER_GLUE(TARGET, MEMBERVARIABLENAME, MEMBERVARIABLETYPE, MEMBERVARIABLE) \
if (pTarget == TARGET && pMemberVariableName->compare(MEMBERVARIABLENAME) == 0) { \
MEMBERVARIABLETYPE pOldVar = MEMBERVARIABLE; \
MEMBERVARIABLE = dynamic_cast<MEMBERVARIABLETYPE>(pNode); \
CC_ASSERT(MEMBERVARIABLE); \
if (pOldVar != MEMBERVARIABLE) { \
CC_SAFE_RELEASE(pOldVar); \
MEMBERVARIABLE->retain(); \
} \
return true; \
}
}
class CC_DLL CCBMemberVariableAssigner {
public:

View File

@ -359,7 +359,8 @@ bool CCBReader::isSpriteSheetLoaded(CCString * pSpriteSheet) {
}
void CCBReader::addLoadedSpriteSheet(CCString * pSpriteSheet) {
pSpriteSheet->retain();
// Since std::set<string> will copy the string from pSpriteSheet, we needn't to retain 'pSpriteSheet'.
// pSpriteSheet->retain();
this->mLoadedSpriteSheets.insert(pSpriteSheet->m_sString);
}

View File

@ -414,7 +414,7 @@ CCSpriteFrame * CCNodeLoader::parsePropTypeSpriteFrame(CCNode * pNode, CCNode *
CCString * spriteFilePath = CCBReader::concat(pCCBReader->getCCBRootPath(), spriteFile);
CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage(spriteFilePath->getCString());
CCRect bounds = CCRect::CCRect(0, 0, texture->getContentSize().width, texture->getContentSize().height);
CCRect bounds = CCRectMake(0, 0, texture->getContentSize().width, texture->getContentSize().height);
spriteFrame = CCSpriteFrame::frameWithTexture(texture, bounds);
} else {
CCSpriteFrameCache * frameCache = CCSpriteFrameCache::sharedSpriteFrameCache();

View File

@ -73,6 +73,7 @@ CCNodeLoader * CCNodeLoaderLibrary::getCCNodeLoader(CCString * pClassName) {
void CCNodeLoaderLibrary::purge(bool pReleaseCCNodeLoaders) {
if(pReleaseCCNodeLoaders) {
for(CCNodeLoaderMap::iterator it = this->mCCNodeLoaders.begin(); it != this->mCCNodeLoaders.end(); it++) {
it->first->release();
it->second->release();
}
}

View File

@ -359,23 +359,24 @@ static std::vector<unsigned short> cc_utf16_vec_from_utf16_str(const unsigned sh
//
//FNTConfig Cache - free functions
//
CCDictionary *configurations = NULL;
static CCDictionary* s_pConfigurations = NULL;
CCBMFontConfiguration* FNTConfigLoadFile( const char *fntFile)
{
CCBMFontConfiguration* pRet = NULL;
if( configurations == NULL )
if( s_pConfigurations == NULL )
{
configurations = new CCDictionary();
s_pConfigurations = new CCDictionary();
}
pRet = (CCBMFontConfiguration*)configurations->objectForKey(fntFile);
pRet = (CCBMFontConfiguration*)s_pConfigurations->objectForKey(fntFile);
if( pRet == NULL )
{
pRet = CCBMFontConfiguration::create(fntFile);
if (pRet)
{
configurations->setObject(pRet, fntFile);
s_pConfigurations->setObject(pRet, fntFile);
}
}
@ -384,10 +385,10 @@ CCBMFontConfiguration* FNTConfigLoadFile( const char *fntFile)
void FNTConfigRemoveCache( void )
{
if (configurations)
if (s_pConfigurations)
{
configurations->removeAllObjects();
CC_SAFE_RELEASE_NULL(configurations);
s_pConfigurations->removeAllObjects();
CC_SAFE_RELEASE_NULL(s_pConfigurations);
}
}
@ -1363,8 +1364,8 @@ void CCLabelBMFont::setFntFile(const char* fntFile)
m_sFntFile = fntFile;
CC_SAFE_RELEASE(m_pConfiguration);
CC_SAFE_RETAIN(newConf);
CC_SAFE_RELEASE(m_pConfiguration);
m_pConfiguration = newConf;
this->setTexture(CCTextureCache::sharedTextureCache()->addImage(m_pConfiguration->getAtlasName()));

View File

@ -44,7 +44,7 @@ public:
@param[in] pszMode The read mode of the file
@param[out] pSize If get the file data succeed the it will be the data size,or it will be 0
@return if success,the pointer of data will be returned,or NULL is returned
@warning If you get the file data succeed,you must delete it after used.
@warning If you get the file data succeed,you must delete[] it after used.
*/
unsigned char* getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize);
@ -53,7 +53,7 @@ public:
@param[in] pszFileName The resource file name which contain the relative path of zip file
@param[out] pSize If get the file data succeed the it will be the data size,or it will be 0
@return if success,the pointer of data will be returned,or NULL is returned
@warning If you get the file data succeed,you must delete it after used.
@warning If you get the file data succeed,you must delete[] it after used.
*/
unsigned char* getFileDataFromZip(const char* pszZipFilePath, const char* pszFileName, unsigned long * pSize);

View File

@ -94,22 +94,28 @@ CCImage::~CCImage()
bool CCImage::initWithImageFile(const char * strPath, EImageFormat eImgFmt/* = eFmtPng*/)
{
CC_UNUSED_PARAM(eImgFmt);
unsigned long nSize;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(strPath), "rb", &nSize);
return initWithImageData(pBuffer, nSize, eImgFmt);
bool bRet = false;
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(strPath), "rb", &nSize);
if (pBuffer != NULL && nSize > 0)
{
bRet = initWithImageData(pBuffer, nSize, eImgFmt);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
bool CCImage::initWithImageFileThreadSafe(const char *fullpath, EImageFormat imageType)
{
CC_UNUSED_PARAM(imageType);
unsigned long nSize;
bool bRet = false;
unsigned long nSize = 0;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
return initWithImageData(pBuffer, nSize, imageType);
if (pBuffer != NULL && nSize > 0)
{
bRet = initWithImageData(pBuffer, nSize, imageType);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
bool CCImage::initWithImageData(void * pData,

View File

@ -83,14 +83,15 @@ bool CCSAXParser::parse(const char* pXMLData, unsigned int uDataLength)
bool CCSAXParser::parse(const char *pszFile)
{
unsigned long size;
char *pBuffer = (char*)CCFileUtils::sharedFileUtils()->getFileData(pszFile, "rt", &size);
if (!pBuffer)
bool bRet = false;
unsigned long size = 0;
char* pBuffer = (char*)CCFileUtils::sharedFileUtils()->getFileData(pszFile, "rt", &size);
if (pBuffer != NULL && size > 0)
{
return false;
bRet = parse(pBuffer, size);
}
return parse(pBuffer, size);
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
void CCSAXParser::startElement(void *ctx, const CC_XML_CHAR *name, const CC_XML_CHAR **atts)

View File

@ -447,7 +447,8 @@ CCArray* ccFileUtils_arrayWithContentsOfFileThreadSafe(const char* pFileName)
unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
{
unsigned char * pBuffer = NULL;
CCAssert(pszFileName != NULL && pSize != NULL && pszMode != NULL, "Invaild parameters.");
*pSize = 0;
do
{
// read the file from hardware

View File

@ -359,23 +359,35 @@ CCImage::~CCImage()
bool CCImage::initWithImageFile(const char * strPath, EImageFormat eImgFmt/* = eFmtPng*/)
{
unsigned long nSize;
CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();
unsigned char *pBuffer = fileUtils->getFileData(fileUtils->fullPathFromRelativePath(strPath), "rb", &nSize);
bool bRet = false;
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(
CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(strPath),
"rb",
&nSize);
return initWithImageData(pBuffer, nSize, eImgFmt);
if (pBuffer != NULL && nSize > 0)
{
bRet = initWithImageData(pBuffer, nSize, eImgFmt);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
bool CCImage::initWithImageFileThreadSafe(const char *fullpath, EImageFormat imageType)
{
CC_UNUSED_PARAM(imageType);
/*
* CCFileUtils::fullPathFromRelativePath() is not thread-safe, it use autorelease().
*/
unsigned long nSize;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
return initWithImageData(pBuffer, nSize, imageType);
bool bRet = false;
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
if (pBuffer != NULL && nSize > 0)
{
bRet = initWithImageData(pBuffer, nSize, imageType);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
return bRet;
}
bool CCImage::initWithImageData(void * pData,

View File

@ -190,10 +190,11 @@ const char *CCFileUtils::fullPathFromRelativeFile(const char *pszFilename, const
return pRet->m_sString.c_str();
}
unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long* pSize)
{
unsigned char * pBuffer = NULL;
unsigned char* pBuffer = NULL;
CCAssert(pszFileName != NULL && pSize != NULL && pszMode != NULL, "Invaild parameters.");
*pSize = 0;
do
{
// read the file from hardware

View File

@ -198,8 +198,8 @@ tImageTGA * tgaLoad(const char *pszFilename)
int mode,total;
tImageTGA *info = NULL;
unsigned long nSize;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(pszFilename, "rb", &nSize);
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(pszFilename, "rb", &nSize);
do
{
@ -270,6 +270,8 @@ tImageTGA * tgaLoad(const char *pszFilename)
}
} while(0);
CC_SAFE_DELETE_ARRAY(pBuffer);
return info;
}

View File

@ -29,14 +29,14 @@ THE SOFTWARE.
#include "ccMacros.h"
#include "CCFileUtils.h"
namespace cocos2d
{
// memory in iPhone is precious
// Should buffer factor be 1.5 instead of 2 ?
#define BUFFER_INC_FACTOR (2)
NS_CC_BEGIN
int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength, unsigned int outLenghtHint)
{
// memory in iPhone is precious
// Should buffer factor be 1.5 instead of 2 ?
#define BUFFER_INC_FACTOR (2)
int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength, unsigned int outLenghtHint)
{
/* ret value */
int err = Z_OK;
@ -99,10 +99,10 @@ namespace cocos2d
*outLength = bufferSize - d_stream.avail_out;
err = inflateEnd(&d_stream);
return err;
}
}
int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLengthHint)
{
int ZipUtils::ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLengthHint)
{
unsigned int outLength = 0;
int err = ccInflateMemoryWithHint(in, inLength, out, &outLength, outLengthHint);
@ -130,16 +130,16 @@ namespace cocos2d
}
return outLength;
}
}
int ZipUtils::ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
{
int ZipUtils::ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
{
// 256k for hint
return ccInflateMemoryWithHint(in, inLength, out, 256 * 1024);
}
}
int ZipUtils::ccInflateGZipFile(const char *path, unsigned char **out)
{
int ZipUtils::ccInflateGZipFile(const char *path, unsigned char **out)
{
int len;
unsigned int offset = 0;
@ -206,21 +206,20 @@ namespace cocos2d
}
return offset;
}
}
int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
{
int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
{
CCAssert(out, "");
CCAssert(&*out, "");
// load file into memory
unsigned char *compressed = NULL;
unsigned char* compressed = NULL;
int fileLen = 0;
compressed = CCFileUtils::sharedFileUtils()->getFileData(path, "rb", (unsigned long *)(&fileLen));
// int fileLen = CCFileUtils::sharedFileUtils()->ccLoadFileIntoMemory( path, &compressed );
unsigned long fileLen = 0;
compressed = CCFileUtils::sharedFileUtils()->getFileData(path, "rb", &fileLen);
if( fileLen < 0 )
if(NULL == compressed || 0 == fileLen)
{
CCLOG("cocos2d: Error loading CCZ compressed file");
return -1;
@ -279,6 +278,6 @@ namespace cocos2d
}
return len;
}
}
} // end of namespace cocos2d
NS_CC_END

View File

@ -438,9 +438,10 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
}
CCImage image;
unsigned long nSize;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath.c_str(), "rb", &nSize);
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath.c_str(), "rb", &nSize);
CC_BREAK_IF(! image.initWithImageData((void*)pBuffer, nSize, eImageFormat));
CC_SAFE_DELETE_ARRAY(pBuffer);
texture = new CCTexture2D();
texture->initWithImage(&image, resolution);
@ -453,8 +454,7 @@ CCTexture2D * CCTextureCache::addImage(const char * path)
#endif
m_pTextures->setObject(texture, pathKey.c_str());
// autorelease prevents possible crash in multithreaded environments
texture->autorelease();
texture->release();
}
else
{
@ -854,9 +854,8 @@ void VolatileTexture::reloadAllTextures()
}
else
{
unsigned long nSize;
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(vt->m_strFileName.c_str(), "rb", &nSize);
unsigned long nSize = 0;
unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(vt->m_strFileName.c_str(), "rb", &nSize);
if (image.initWithImageData((void*)pBuffer, nSize, vt->m_FmtImage))
{
@ -865,6 +864,8 @@ void VolatileTexture::reloadAllTextures()
vt->texture->initWithImage(&image);
CCTexture2D::setDefaultAlphaPixelFormat(oldPixelFormat);
}
CC_SAFE_DELETE_ARRAY(pBuffer);
}
}
break;

View File

@ -421,12 +421,12 @@ bool CCTexturePVR::initWithContentsOfFile(const char* path)
if (!unpackPVRData(pvrdata, pvrlen) || !createGLTexture())
{
delete [] pvrdata;
CC_SAFE_DELETE_ARRAY(pvrdata);
this->release();
return false;
}
delete [] pvrdata;
CC_SAFE_DELETE_ARRAY(pvrdata);
return true;
}

View File

@ -5,6 +5,15 @@
USING_NS_CC;
USING_NS_CC_EXT;
ButtonTestLayer::ButtonTestLayer()
: mCCControlEventLabel(NULL)
{}
ButtonTestLayer::~ButtonTestLayer()
{
CC_SAFE_RELEASE(mCCControlEventLabel);
}
SEL_MenuHandler ButtonTestLayer::onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName) {
return NULL;
}

View File

@ -11,16 +11,19 @@ class ButtonTestLayer
, public cocos2d::extension::CCBMemberVariableAssigner
, public cocos2d::extension::CCBSelectorResolver
{
public:
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(ButtonTestLayer, node);
ButtonTestLayer();
virtual ~ButtonTestLayer();
virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget, cocos2d::CCString * pSelectorName);
virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(cocos2d::CCObject * pTarget, cocos2d::CCString * pSelectorName);
virtual bool onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, cocos2d::CCString * pMemberVariableName, cocos2d::CCNode * pNode);
void onCCControlButtonClicked(cocos2d::CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent);
private:
private:
cocos2d::CCLabelBMFont * mCCControlEventLabel;
};

View File

@ -14,6 +14,17 @@
USING_NS_CC;
USING_NS_CC_EXT;
HelloCocosBuilderLayer::HelloCocosBuilderLayer()
: mBurstSprite(NULL)
, mTestTitleLabelTTF(NULL)
{}
HelloCocosBuilderLayer::~HelloCocosBuilderLayer()
{
CC_SAFE_RELEASE(mBurstSprite);
CC_SAFE_RELEASE(mTestTitleLabelTTF);
}
void HelloCocosBuilderLayer::openTest(const char * pCCBFileName, const char * pCCNodeName, CCNodeLoader * pCCNodeLoader) {
/* Create an autorelease CCNodeLoaderLibrary. */
CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();

View File

@ -26,6 +26,9 @@ class HelloCocosBuilderLayer
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(HelloCocosBuilderLayer, node);
HelloCocosBuilderLayer();
virtual ~HelloCocosBuilderLayer();
void openTest(const char * pCCBFileName, const char * pCCNodeName = NULL, cocos2d::extension::CCNodeLoader * pCCNodeLoader = NULL);
virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget, cocos2d::CCString * pSelectorName);

View File

@ -5,6 +5,14 @@
USING_NS_CC;
USING_NS_CC_EXT;
MenuTestLayer::MenuTestLayer()
: mMenuItemStatusLabelBMFont(NULL)
{}
MenuTestLayer::~MenuTestLayer()
{
CC_SAFE_RELEASE(mMenuItemStatusLabelBMFont);
}
SEL_MenuHandler MenuTestLayer::onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName) {
CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "onMenuItemAClicked", MenuTestLayer::onMenuItemAClicked);

View File

@ -14,6 +14,9 @@ class MenuTestLayer
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_WITH_INIT_METHOD(MenuTestLayer, node);
MenuTestLayer();
virtual ~MenuTestLayer();
virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget, cocos2d::CCString * pSelectorName);
virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(cocos2d::CCObject * pTarget, cocos2d::CCString * pSelectorName);
virtual bool onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, cocos2d::CCString * pMemberVariableName, cocos2d::CCNode * pNode);