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