Eli*_*Eli 1 iphone pointers exc-bad-access objective-c short-circuiting
我在Objective-C中有一行非常简单的代码:
if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]])
Run Code Online (Sandbox Code Playgroud)
我偶尔也无缘无故地说,游戏在EXC-BAD-ACCESS的这行代码上崩溃了.它通常似乎是关于某些东西被从游戏领域中移除的时间,所以我猜测selectedEntity 是什么被 dealloc'd,然后这结果.除了是不可能选择退出实体(但谁知道,也许这实际上不是真正的在我的代码......),事实上,我特别检查,看看是否有是一个selectedEntity之前,我访问它意味着,我不该这里有任何问题.Objective-C应该支持布尔短约束,但似乎不是编辑:看起来像短路与问题无关.
另外,我在这个代码块周围放了一个@ try/@ catch,因为我知道它偶尔会爆炸,但是这似乎被忽略了(我猜测EXC-BAD-ACCESS无法捕获).
所以基本上我想知道是否有人知道我可以抓住这个并把它抛出的方式(因为我不关心这个错误,只要它不会让游戏崩溃)或者可以解释为什么它可能会发生.我知道Objective-C用"nil"值做了奇怪的事情,所以我猜它指的是一些既不是对象指针也不是nil的奇怪空间.
编辑:只是为了澄清,我知道下面的代码是错误的,这是我猜测在我的程序中发生的事情.我问这是否会导致问题 - 确实如此.:-)
编辑:看起来有一个边缘案例,允许您在删除之前选择一个实体.所以,似乎代码的进展如下:
selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];
Run Code Online (Sandbox Code Playgroud)
所以我猜测因为Autorelease池还没有被释放,所以对象不是nil,但是它的保留计数是0,所以不允许它被访问...或者沿着这些线路?
此外,我的游戏是单线程的,所以这不是一个线程问题.
编辑:我以两种方式修复了问题.首先,我不允许在该边缘案例中选择实体.其次,不是只调用[entities removeObjectAtIndex:i](删除任何将被删除的实体的代码),而是将其更改为:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
Run Code Online (Sandbox Code Playgroud)
正如jib建议的那样,确保在释放变量的同时为变量分配nil.
这与短路无关.Objective-C将消息写为nil,因此selectedEntity != nil不需要检查(因为对于BOOL返回类型,messages-to-nil将返回NO).
EXC_BAD_ACCESS不是可捕获的异常.这是一个灾难性的失败,通常是由于试图跟随无效指针造成的.
更有可能的是,在执行代码之前已经释放了selectedEntity指向的任何对象.因此,它既不是零也不是有效的对象.
打开NSZombies并重试.
如果您的应用程序是线程化的,您是否正确地跨线程同步selectedEntity(请记住,通常,不支持从辅助线程进行UI操作)?
您的帖子已经过编辑,表明修复程序是:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题,因为NSMutableArray会在删除时释放对象.如果保留计数降至零,则取消分配对象,然后selectedEntity指向解除分配的对象.
小智 6
如果一个对象(selectedEntity)已被释放并且dealloc'd它不是== nil.它是一个指向任意一块内存的指针,并引用它(if(selectedEntity!= nil)是一个编程错误(EXC_BAD_ACCESS).
因此,常见的obj-c范式: -
[selectedEntity release]; selectedEntity = nil;
| 归档时间: |
|
| 查看次数: |
4753 次 |
| 最近记录: |