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

由于项目原因,骨骼动画需要进行异步加载,在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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值