«EXC_BAD_ACCESS: невозможно восстановить ранее выбранный кадр» — переменные стека не очищаются

Со ссылкой на вопрос здесь.

Решения, представленные в этом потоке, включают:

  1. Умело относитесь к тому, где и сколько переменных вы объявляете, чтобы они попадали в стек.
  2. При необходимости отключите Guard Malloc.

Кроме того, в целом: 3. Убедитесь, что вы освобождаете переменную, для которой вы фактически выделили память!!

У меня нет ни одной из вышеперечисленных проблем. В функциях я использую очень мало переменных, размещенных в стеке, скажем, 2-3 в каждой. Но поскольку функции вызываются в цикле несколько раз, создается впечатление, что это вызывает исключение.

И вот кикер, это происходит не только для статически выделенных переменных, но и для кучи! Я получаю сообщения об ошибках страниц в объявлениях Auto-released переменных NSNumber, которые я использую внутри цикла, а также словарь, который я разумно выделяю и освобождаю в рамках функции каждый раз, когда она вызывается.

Так почему же это происходит и почему, черт возьми, это влияет на переменные кучи? Я вообще ничего не понимаю, пожалуйста, проясните это. :)

Я на IOS5 с XCode 4.2, симулятором iPhone/iPad.

Спасибо!

С уважением, Дев

Изменить: пример кода
- (void)doSomething {
NSInteger fun = 3;
NSInteger time = 4;
NSInteger overload = fun*time;
NSString *string = [NSString stringWithFormat:@"%d",overload];
NSObject *myCustomObject = [[NSObject alloc] init];
[myCustomDictionary setObject:myCustomObject forKey:string];
[myCustomObject release];
//myCustomDictionary is an iVar, alloced in the class's init method, and released in dealloc and not touched anywhere in between
}
//doSomething gets called several times through the course of execution as the state of the view changes, the user interacts with it etc, often 2-3 times during one state change.

Код намеренно расплывчатый, но в то же время он ТОЧНО такой же простой, как и в образце. Как и остальной код во всем проекте. Несколько функций, каждая из которых выполняет небольшой объем работы, так же хорошо самодостаточны в отношении памяти, как и эта.

Раньше я сталкивался с проблемами EXC_BAD_ACCESS и в этот момент ссылался на этот вопрос. Однако в моем случае я не создавал несколько переменных в стеке в цикле, они неоднократно создавались функцией, которая вызывалась несколько раз в ходе выполнения. В идеале переменные должны быть уничтожены в конце области видимости функции. Не знаю, почему этого не произошло.

Во всяком случае, чтобы решить эту проблему и предотвратить многократное выделение, я в конечном итоге объявил свои переменные, выделенные в стеке, как все static. Это плохая практика, но именно это я должен был сделать, чтобы заставить ее работать. И это работало, пока я снова не столкнулся с проблемой с функцией «doSomething».

Таким образом, сложность в «doSomething» заключалась в том, что у меня не только создавались переменные, выделенные в стеке, но и куча вещей. Итак, я сначала начал получать EXC_BAD_ACCESS для переменных NSInteger, после чего снова попытался исправить это, объявив их статическими. Это сработало, но теперь EXC_BAD_ACCESS начал появляться в автоматически освобождаемой переменной и, наконец, в пользовательской выделенной переменной, что и привело меня в тупик. Я следовал всем правилам управления памятью, и у меня были переменные стека и кучи, которые меня раздражали. Если бы это была только куча или стек внутри цикла, я мог бы понять, что где-то есть ошибка. Но здесь нет ни того, ни другого, это совершенно невинные переменные, размещаемые в стеке внутри ОДНОЙ функции, которая НЕ вызывается в цикле, и обычные переменные с автоматическим освобождением, которые никогда не получают сохранения или освобождения, выброшенные на них из другого места в коде. Что еще хуже, так это то, что точки сбоя случайны - не только в этой функции, но практически в каждой, которая вызывается несколько раз в ходе выполнения проекта.

Edit2: Оказывается, в данном случае это моя вина. Подробности смотрите в моем ответе. Извините за потраченное время людей. :\


person Dev Kanchen    schedule 15.02.2012    source источник


Ответы (3)


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

Исходя из моего опыта, когда вы не получаете tarce стека, это означает, что вы дважды выпускаете. Зомби — это способ найти свое двойное освобождение.

Перейдите к: Product -> Profile, а затем выберите "Zombies" из списка. Запустите приложение и выполните любую задачу, которая вызывает сбой. Если проблема заключается в двойном выпуске, появится всплывающее окно. Выберите стрелку во всплывающем окне, и она точно скажет вам, какой объект дважды освобождается, и покажет вам цикл сохранения.

person aryaxt    schedule 16.02.2012
comment
Пожалуйста, обратитесь к моему ответу. Я не могу принять это прямо сейчас, так как кажется, что я могу принять свой собственный ответ только через 2 дня после того, как задал вопрос, или что-то в этом роде. - person Dev Kanchen; 16.02.2012
comment
И, как я уже упоминал, Zombies применимы к объектам, объявленным в куче. Я столкнулся с той же проблемой и с переменными STACK, так что это была не проблема сохранения/выпуска, а то, что приложению просто не хватало памяти после x итераций бесконечного цикла, как поясняется в моем ответе. - person Dev Kanchen; 16.02.2012

Без какого-либо кода, опубликованного в вашем вопросе, и видя, что вы используете iOS 5 и Xcode 4.2, мой лучший совет для вас: в Xcode перейдите к Edit>Refactor>Convert to Objective-C ARC и попрощайтесь со всеми своими головными болями по управлению памятью.

ARC выполняет все управление памятью за вас. Вам не нужно сохранять, освобождать или писать методы освобождения. В большинстве случаев вам не нужно беспокоиться об управлении памятью. Вы оставите загадочные EXC_BAD_ACCESS аварии позади. То, как это работает, суперэффективно. Компилятор сохраняет и выпускает для вас, а затем оптимизирует. Вам даже не придется видеть код.

person jackslash    schedule 15.02.2012
comment
Проблемы связаны как со статически размещенными объектами, так и с чисто автовыпущенными объектами, а не так сказать кастомными, так что я сомневаюсь, что ARC поможет. Я могу отредактировать вопрос с помощью примера кода, если это поможет. - person Dev Kanchen; 16.02.2012

Ах, Боже, я не верю в это.

Проблемы, с которыми мы столкнулись ранее с переменными NSInteger, размещенными в стеке, сохраняются, но в этом случае это была полностью моя вина.

"doSomething" было частью длинной цепочки событий, которая из-за какой-то глупой небрежности с моей стороны в конечном итоге зацикливается несколько раз, что, по праву и должно быть, приводит к тому, что приложению не хватает памяти. . Будь то с переменными стека или с распределенными переменными, сидящими в куче, с бесконечным циклом, он так или иначе рухнет. :)

Так что сбой совершенно справедлив, просто в данном случае перепутали с предыдущей проблемой, которая оказалась не связанной. :(

Извините, что отнял у всех время.

person Dev Kanchen    schedule 16.02.2012