您的位置:首页 > 移动开发 > Cocos引擎

Cocos2dx android下异步加载骨骼动画崩溃问题

2014-11-27 21:18 337 查看
由于项目原因,骨骼动画需要进行异步加载,在windows和ios下面一切很正常。没遇到什么奇葩的事情。

在发布到Android时发现,只要进行异步加载骨骼动画,程序就崩溃掉。

查看日志发现:

11-27 13:00:43.420: E/cocos2d-x assert(5346): C:\work\LOL\cocos2d-x-2.1.4\cocos2d-x-2.1.4/cocos2dx/support/zip_support/ZipUtils.cpp function:getFileData line:579

在这里断言了,于是去查看代码:        int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);

再往下看日志:

11-27 13:00:43.430: A/libc(5346): Fatal signal 11 (SIGSEGV) at 0x00000030 (code=1), thread 5409 (Thread-333)

在单线程模式下int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);

是不会出现错误的,由于有用多线程进行加载, thread 5409 (Thread-333)指示的线程id不同,也就说明ZipUtils.cpp在多线程模式下加载出现了冲突。

后面查资料发现,android文件在系统中是以压缩包形式存在,那么在加载数据时,就会出现多个线程同时访问同一份资源。也就出现了上面这个错误

查到问题了,那解决方案自然就有了。

在unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)中加个线程锁,就能保证线程安全了

// 自动线程锁

class AutoLock
{
public:
AutoLock(pthread_mutex_t* pMutex)
{
m_pMutex = pMutex;
pthread_mutex_lock(m_pMutex);
};
~AutoLock()
{
pthread_mutex_unlock(m_pMutex);
};
private:
pthread_mutex_t* m_pMutex;
};
初始化线程锁
ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
: _data(new ZipFilePrivate)
, _dataThread(new ZipFilePrivate)
{
_data->zipFile = unzOpen(zipFile.c_str());
_dataThread->zipFile = unzOpen(zipFile.c_str());
if (_data->zipFile && _dataThread->zipFile)
{
setFilter(filter);
}
pthread_mutex_init(&m_SDKMsgQueueMutex, NULL);
}
释放线程锁

ZipFile::~ZipFile()
{
if (_data && _data->zipFile)
{
unzClose(_data->zipFile);
}
if (_dataThread && _dataThread->zipFile)
{
unzClose(_dataThread->zipFile);
}
CC_SAFE_DELETE(_data);
CC_SAFE_DELETE(_dataThread);
pthread_mutex_destroy(&m_SDKMsgQueueMutex);
}


加线程锁

unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)
{
AutoLock lock(&m_SDKMsgQueueMutex);
unsigned char * pBuffer = NULL;
if (pSize)
{
*pSize = 0;
}

do
{
CC_BREAK_IF(!data->zipFile);
CC_BREAK_IF(fileName.empty());

ZipFilePrivate::FileListContainer::const_iterator it = data->fileList.find(fileName);
CC_BREAK_IF(it ==  data->fileList.end());

ZipEntryInfo fileInfo = it->second;

int nRet = unzGoToFilePos(data->zipFile, &fileInfo.pos);
CC_BREAK_IF(UNZ_OK != nRet);

nRet = unzOpenCurrentFile(data->zipFile);
CC_BREAK_IF(UNZ_OK != nRet);

pBuffer = new unsigned char[fileInfo.uncompressed_size];
int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);
char buf[1024] = {0};
sprintf(buf, "the file size is wrong size[%d] uncompressed_size[%d] file name:%s", nSize, (int)fileInfo.uncompressed_size, fileName.c_str());
CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, buf);

if (pSize)
{
*pSize = fileInfo.uncompressed_size;
}
unzCloseCurrentFile(data->zipFile);
} while (0);

return pBuffer;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息