У меня есть очень простая строка кода в Objective-C:
if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]])
Время от времени и без причины я могу сказать, что игра вылетает на этой строке кода с 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];
Так что я предполагаю, что, поскольку пул Autorelease еще не был освобожден, объект не равен nil, но его счетчик хранения равен 0, поэтому доступ к нему все равно запрещен ... или что-то в этом роде?
Кроме того, моя игра однопоточная, так что это не проблема с потоками.
РЕДАКТИРОВАТЬ: я исправил проблему двумя способами. Во-первых, я не позволил выбрать сущность в этом крайнем случае. Во-вторых, вместо того, чтобы просто вызывать [entity removeObjectAtIndex: i] (код для удаления любых сущностей, которые будут удалены), я изменил его на:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
Просто убедитесь, что вы присваиваете nil переменной в то же самое время, когда вы ее отпускаете, как предложено в кливере.