«EXC_BAD_ACCESS: невозможно восстановить ранее выбранный кадр» - переменные стека не очищаются - PullRequest
1 голос
/ 16 февраля 2012

Применительно к вопросу здесь .

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

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

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

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

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

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

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

Спасибо!

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

Редактировать: Пример кода <br> - (void)doSomething {<br> NSInteger fun = 3;<br> NSInteger time = 4;<br> NSInteger overload = fun*time;<br> NSString *string = [NSString stringWithFormat:@"%d",overload];<br> NSObject *myCustomObject = [[NSObject alloc] init];<br> [myCustomDictionary setObject:myCustomObject forKey:string];<br> [myCustomObject release];<br> //myCustomDictionary is an iVar, alloced in the class's init method, and released in dealloc and not touched anywhere in between<br> }<br> //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.<br>

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

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

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

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

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

Ответы [ 3 ]

1 голос
/ 16 февраля 2012

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

Судя по моему опыту, когда вы не получаете стак-тарс, это означает, что вы дважды выпускаете. Зомби - это способ найти свой двойной релиз.

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

0 голосов
/ 16 февраля 2012

Ах, черт возьми, я не верю этому.

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

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

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

Извините за трату времени всех.

0 голосов
/ 16 февраля 2012

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

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

...