Как отладить ARC, удаляя объект, когда он не должен - PullRequest
3 голосов
/ 21 марта 2012

В моей игре для iOS (скомпилированной с ARC) есть случай, когда объект (ivar, NSMutableDictionary) удаляется в сборке выпуска, хотя это явно не должно быть. В сборке отладки все нормально.

Я пытаюсь найти лучший способ отладить это. Если я ставлю какие-либо проверки на объект, он зависает как следует. Я знаю, что объект используется, потому что приложение падает, поэтому к объектам обращаются.

Я использовал объекты Zombie, чтобы сказать, что объект удаляется, но я не знаю, где и когда это происходит.

Есть ли способ узнать, когда компилятор считает, что эти объекты больше не нужны, или когда он на самом деле удаляется (что может ничего не сказать, если он находится в пуле автоматического выпуска).

У кого-нибудь есть хороший совет, чтобы отследить это? Я не хочу просто называть это ошибкой компилятора, но я не могу понять, как компилятор мог думать, что на этот объект больше нет ссылок, так как он упоминается повсюду. Объект, который содержит ivar, - это место, где выполняется весь мой код, так что он явно все еще существует (и если бы его не было, все происходило бы намного хуже).

А пока я просто оставлю одну строку кода отладки, из-за которой объект не будет удален, но я ненавижу поставлять приложение с этим решением.

Спасибо.

Ответы [ 3 ]

1 голос
/ 25 апреля 2012

Сегодня мы столкнулись с проблемой, которая звучит так же, как вы столкнулись здесь. Мы загружаем класс с помощью пользовательского метода из NSDictionary, загруженного из plist-файла, и наше приложение теперь аварийно завершает работу в конце этого метода из-за, похоже, двойного выпуска. Мы обнаружили, что отключение оптимизации двоичного файла релиза - это все, что мы могли сделать, чтобы это исправить.

Мы не изменили никакого связанного кода с методом, который сейчас вызывает сбой (он работал нормально около 2 месяцев), и после многих часов попыток выяснить, где была проблема, мы обнаружили, что На данный момент мы можем исправить это, изменив «Уровень оптимизации» на «Нет» для нашего кода выпуска. Перейти к ..

Проект -> Цели -> Двоичное имя -> Настройки сборки -> Уровень оптимизации -> Выпуск

И установите для него значение «Нет -O0».

Я могу только предположить, что в оптимизаторе происходит очень странная ошибка, но я надеюсь, что это поможет вам!

1 голос
/ 23 июня 2012

Это происходит и со мной, но со слабыми IBOutlets.

@property (nonatomic, weak) IBOutlet UIView *blahView;

…

[self.blahView removeFromSuperview];
[self.otherView addSubview:self.blahView];

После того, как компилятор первой строки решит, что больше нет ссылок на объект, и выпустит / удалит его.

Сохранение слабого эталонного ivar и использование временной переменной (в области видимости) для этого убеждает компилятор не выпускать его.

UIView *blahView = self.blahView;
[blahView removeFromSuperview];
[self.otherView addSubview:blahView];

Решает ли это вашу проблему?

1 голос
/ 21 марта 2012

Место для размещения вашего кода отладки находится в методе dealloc объекта. Вы можете установить точку останова здесь (даже в режиме Release) и посмотреть, в какой момент она исчезнет.

Наиболее вероятная причина заключается в том, что какой-то фрагмент кода либо переупорядочивается, либо исключается из версии.

Когда вы говорите «на него ссылаются повсюду», вы имеете в виду, что у вас есть объекты, которые имеют сильную ссылку на него в своих свойствах? Первое правило управления памятью - сохранять (помещать в ивар) то, что вас волнует, и освобождать то, что вам больше не нужно. Если у вас есть объекты, которые заботятся об этом объекте, то они должны иметь сильное свойство, указывающее на него. Если они это сделают, то это точно не должно исчезнуть.


Сильные указатели в ARC указывают на серьезную проблему в вашем коде. Я бы начал с поиска везде, где у вас есть соединение (в частности, __bridge). Убедитесь, что вы не передаете объекты неверно указателям.

Следите за любым использованием массивов C. Если вы выйдете из конца массива C, вы можете повредить другую память, что может вызвать проблемы такого рода.

Аналогичным образом наблюдайте за любым использованием всего, что принимает аргумент length, например, в NSString и NSData. Если вы передаете слишком длинное значение, вы можете выйти из конца данных и испортить другие переменные. Точно так же что-нибудь с необработанными указателями через malloc память.

...