【发布时间】:2011-04-17 00:27:28
【问题描述】:
我遇到了一个 Objective-C 对象(在 iOS 游戏应用程序中)被神秘地释放的问题。
该对象是一个 GameCharacter 实例,其实例化如下:
for (int c = 0; c < kNrOfGuards; c++) {
GameCharacter* guard = [[GameCharacter alloc] initGuard:self sprite:guardSprite];
[characterArray addObject:guard];
[guard release];
}
我还有一个查找 GameCharacter 的便捷方法:
- (GameCharacter*)findCharacterWithIndex:(int)index {
return [characterArray objectAtIndex:index];
}
产生错误的代码如下:
for (int c = 0; c < [self characterCount]; c++) {
GameCharacter* tempCharacter = [self findCharacterWithIndex:c];
if (tempCharacter.playerId == playerIndex]) {
...
}
}
运行此代码一段时间(从不立即)在控制台中生成错误:
[GameCharacter playerId]:消息发送到已释放实例 0x4e47560
通过NSZombieEnabled trick,我设法找到了导致问题的对象,但我仍然无法理解为什么这个对象被释放。在我的代码中搜索“release”/“dealloc”不会产生任何线索。
我尝试将“释放”(甚至添加“保留”!)到分配/初始化循环(见顶部),它似乎延长了应用程序可以运行的时间,但不能完全消除问题。
任何提示将不胜感激!
编辑
感谢 quixoto、Olie、Eiko 等,我发现是我的 GameCharacter 对象正在被释放,但我仍然不明白为什么。以下是按时间倒序排列的跟踪日志:
#0 -[GameCharacter dealloc]
#1 objc_setProperty
#2 -[TiledGroundLayer setSelectedCharacter:]
#3 -[TiledGroundLayer selectNextCharacterForPlayer:searchStep:]
#4 -[GameScene selectNextCharacter:]
#5 -[GameScene endTurn]
#6 -[HUDLayer onClickDone:]
这里发生的情况是,用户单击“完成”,屏幕上选定的字符被更改,因此 TiledGroundLayer 上的属性selectedCharacter (步骤#2-4)。由于selectedCharacter 拥有之前的 GameCharacter 对象,它似乎正在被释放。但是为什么 NSMutableArray ([characterArray addObject:guard];) 没有正确保留它?
【问题讨论】:
-
您的 characterArray 变量是否创建为
[NSMutableArray array]或[[NSMutableArray init] alloc]? -
@Tom - 这些代码 sn-ps 存在于哪些类中?看起来您在其他地方有与导致 dealloc 的 characterArray 交互的代码。例如,可能与从数组中删除对象相关联 - 会发生这种情况吗?
-
我会仔细查看 characterArray 以及它何时被释放。因为你有一个方便的函数来返回一个守卫,你可以很容易地在 characterArray 之后持有它,并且它的所有内容都被释放。如果您没有方便的方法(并且我在这里看不到它的好处),您可以在需要时从数组中获取防护,并更加确定此时 characterArray 仍然是必需的并且有效。
-
在
GameCharacter中的dealloc方法的顶部添加一个断点。无论如何,你会看到谁拉了最后一个版本。 -
@jojaba:它被创建为
characterArray = [[NSMutableArray alloc] init];
标签: iphone objective-c memory