我在 Objective-C 中有一行非常简单的代码:
if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]])
有时,我无法判断,游戏在这行代码上崩溃,并带有 EXC-BAD-ACCESS。通常似乎是从比赛场地中移除某些东西的时间,所以我猜测selectedEntity是什么被释放了,然后就是这个结果。除了不可能选择退出实体(但谁知道,也许这在我的代码中实际上并非如此......),事实上我在访问之前专门检查是否存在selectedEntity意味着我应该这里没有任何问题。Objective-C 应该支持布尔短路,但它似乎不是编辑:看起来短路与问题无关。
另外,我在这个代码块周围放了一个@try/@catch,因为我知道它每隔一段时间就会爆炸,但这似乎被忽略了(我猜 EXC-BAD-ACCESS 无法被捕获)。
所以基本上我想知道是否有人知道我可以抓住它并把它扔掉(因为我不在乎这个错误,只要它不会导致游戏崩溃)或者可以解释为什么它可能会发生. 我知道 Objective-C 用“nil”值做了一些奇怪的事情,所以我猜它指向一些既不是对象指针也不是 nil 的奇怪空间。
编辑:澄清一下,我知道下面的代码是错误的,这就是我猜想在我的程序中发生的事情。我在问这是否会导致问题——确实如此。:-)
编辑:看起来有一个边缘案例允许您在实体被删除之前选择它。所以,看起来代码的进展是这样的:
selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];
所以我猜是因为 Autorelease 池还没有被释放,所以对象不是 nil,但它的保留计数是 0,所以无论如何都不允许访问它......或者类似的东西?
另外,我的游戏是单线程的,所以这不是线程问题。
编辑:我通过两种方式解决了这个问题。首先,我不允许在那个边缘案例中选择实体。其次,我不只是调用 [entities removeObjectAtIndex:i] (删除将被删除的任何实体的代码),而是将其更改为:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
只需确保在释放变量的同时将 nil 分配给变量,正如 jib 建议的那样。