cocos2d 3.11.1使用粒子效果引起的EXC_BAD_ACCESS问题
来源:互联网 发布:淘宝new balance旗舰店 编辑:程序博客网 时间:2024/05/22 17:13
最近准备构建IOS的包,在运行时进入游戏场景之前直接crash掉了。在CCEAGLView-ios.mm文件中抛出了一个EXC_BAD_ACCESS的错误。
安卓和win32平台上运行都是没问题的。
错位定位的代码位置是
#endif // __IPHONE_4_0 if(![context_ presentRenderbuffer:GL_RENDERBUFFER]) {// CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__); }#if COCOS2D_DEBUG
之前没接触个这种错误,因此查了一下这个EXC_BAD_ACCESS到底是何方神圣!
总结了一下,简单来说就是:当遇到EXC_BAD_ACCESS这个错误,那就意味着你向一个已经释放的对象发送消息。(大部分都是这样,当然也有特例)
详细的解释:当您向一个对象发送消息时,指向该对象的指针将会被引用。这意味着你获取了指针所指的内存地址,并访问该存储区域的值。
当存储器区域不再映射到你的应用时,即改内存区域在你认为使用的时候却没有使用,则改内存区域是无法访问的。这时内核就会抛出一个异常(EXC),表明你的应用程序不能访问该存储区域(BAD ACCESS)。简言之,当你碰到了EXC_BAD_ACCESS时,意味着你试图发送消息到一个内存块,但该内存块无法发送该消息。但某些情况下,EXC_BAD_ACCESS是由某个被损坏的指针引起的,当引用损坏的指针时,也会抛出该异常。
cocos2d: QuadCommand: resizing index size from [-1] to [6]
通过log日志可以看出跟QuadCommand有关系,且上面这条日志是加入了游戏背景的粒子后引起的,所以我断定了跟粒子效果有关系。
先看看QuadCommand相关的代码:
void QuadCommand::reIndex(int indicesCount){ if (indicesCount > __indexCapacity) { CCLOG("cocos2d: QuadCommand: resizing index size from [%d] to [%d]", __indexCapacity, indicesCount); __indices = (GLushort*) realloc(__indices, indicesCount * sizeof(__indices[0])); __indexCapacity = indicesCount; } for( int i=0; i < __indexCapacity/6; i++) { __indices[i*6+0] = (GLushort) (i*4+0); __indices[i*6+1] = (GLushort) (i*4+1); __indices[i*6+2] = (GLushort) (i*4+2); __indices[i*6+3] = (GLushort) (i*4+3); __indices[i*6+4] = (GLushort) (i*4+2); __indices[i*6+5] = (GLushort) (i*4+1); } _indexSize = indicesCount;}
这里有一个问题,如果执行reIndex次数过多,那么可能出现一种情况,针对realloc函数如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)老块被放回堆上。,按照上面对EXC_BAD_ACCESSD的解释,可以想到_indices是正在被使用的,即Frame在Draw的过程中数据可能被移动了,那么Frame之前映射到的存储器区域被修改,则导致在绘制想访问
该存储器位置时,无法访问而抛出异常。
参考了http://discuss.cocos2d-x.org/t/exc-bad-access-random-crashes-on-ios-context-presentrenderbuffer/28494/9
解决方案,修改reIndex函数,在绘制玩Frame后,将_indices内存释放掉:
void QuadCommand::reIndex(int indicesCount){ if (indicesCount > __indexCapacity) { CCLOG("cocos2d: QuadCommand: resizing index size from [%d] to [%d]", __indexCapacity, indicesCount); auto tmpindices = __indices; __indices = (GLushort*)malloc(indicesCount * sizeof(__indices[0])); void** listenerHolder = new void*(); cocos2d::EventListenerCustom* listener = cocos2d::Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_DRAW, [=](cocos2d::EventCustom *event) { if (tmpindices) { free(tmpindices); } // unregister event listener cocos2d::Director::getInstance()->getEventDispatcher()->removeEventListener((EventListener*)*listenerHolder); if (listenerHolder) { delete listenerHolder; } }); *listenerHolder = listener; __indexCapacity = indicesCount; } for (int i = 0; i < __indexCapacity / 6; i++) { __indices[i * 6 + 0] = (GLushort)(i * 4 + 0); __indices[i * 6 + 1] = (GLushort)(i * 4 + 1); __indices[i * 6 + 2] = (GLushort)(i * 4 + 2); __indices[i * 6 + 3] = (GLushort)(i * 4 + 3); __indices[i * 6 + 4] = (GLushort)(i * 4 + 2); __indices[i * 6 + 5] = (GLushort)(i * 4 + 1); } _indexSize = indicesCount;}
后面在看3.15的时候,发现官方解决了这个问题,且方案应该更为妥当。
将原来的_indices放入_ownedIndices中,这样保证原有的frame映射的存储器区域不会放生改变,在析构函数中释放_ownedIndices。这样做也避免了过多的反复resizing即malloc.
如若不想替换引擎可以手动替换掉3.15下 cocos/render/CCQuadCommand.cpp和
对应.h文件,即可解决crash的问题。
- cocos2d 3.11.1使用粒子效果引起的EXC_BAD_ACCESS问题
- cocos2d---粒子效果1
- cocos2d-x 的粒子效果
- 粒子效果CCParticleSystemQuad粒子编辑器ParticleEditor的使用---cocos2d-x学习之路[5]
- Cocos2d-X 定义系统的粒子效果
- cocos2d 粒子效果以及Particle Designer粒子工具的学习
- Cocos2d-x3.1 粒子效果示例
- Cocos2d-x3.1 粒子效果示例
- cocos2d 粒子效果2
- cocos2d-iphone粒子效果
- Cocos2d-x粒子效果
- cocos2d-06 粒子效果
- Cocos2d 粒子效果
- cocos2d-x 粒子效果
- Cocos2d-JS 粒子效果
- Cocos2d-x3.1粒子使用
- 《Cocos2d学习之路》五,粒子效果,Actions,以及中文显示问题的解决
- cocos2d-html5 粒子系统的使用
- 递归求序列最大最小值
- 在mysql数据库中保存emoji特殊字符
- OJ.2480: 分数求和
- SGE集群使用
- 刚上线网站SEO优化如何做好网站外链建设
- cocos2d 3.11.1使用粒子效果引起的EXC_BAD_ACCESS问题
- Java线程浅析(三)
- 学习java点滴
- 《统计学习方法》 逻辑斯谛回归(logistic regression) Python实现
- (转)被遗忘的哪些付出精力取得的东西
- mybatis的resultType和resultMap基础用法
- Python 连接sqlserver数据库
- nginx负载均衡
- 计算机考试C随笔二