EXC_BAD_ACCESS в main () с ARC, но без подсказки об ошибке - PullRequest
6 голосов
/ 09 февраля 2012

У меня заканчиваются идеи.Я получаю EXC_BAD_ACCESS по проекту с использованием ARC.По словам отладчика, это в пределах main().NSZombieEnabled установлен в YES, но я не вижу никакого стека вызовов, ни Class / Type, ни чего-либо.То же самое для инспектора / профиля.Все, что я получаю, это "тайм-аут сеанса" через некоторое время после сбоя приложения.

И это трудно найти в моем коде.

Я устанавливаю трассировки вроде

NSLog(@"CrashLog: <%@:%@:%d:%s>", NSStringFromClass([self class]),
NSStringFromSelector(_cmd), __LINE__, __FILE__);

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

Есть идеи, как изолировать проблему?

Тим предложил использовать обратную трассировку (bt) в gdb.Результат:

#0  0x0be87580 in TI::Favonius::BeamSearch::choose_hit_test_node ()
#1  0x0be87b5f in TI::Favonius::BeamSearch::update_for_touch ()
#2  0x0be8ee32 in TI::Favonius::StrokeBuildManager::update_search_for_touch ()
#3  0x0be8f58f in TI::Favonius::StrokeBuildManager::key_down_or_drag_hit_test_for_UI ()
#4  0x0be6ba8b in TIInputManagerZephyr::simulate_touches_for_input_string ()
#5  0x0be7e5d9 in -[TIKeyboardInputManagerZephyr candidates] ()
#6  0x00678345 in -[UIKeyboardImpl generateAutocorrectionReplacements:] ()
#7  0x007dcaec in __71-[UITextInteractionAssistant scheduleReplacementsForRange:withOptions:]_block_invoke_0 ()
#8  0x007f6db2 in -[UITextSelectionView calculateAndShowReplacements:] ()
#9  0x00e255fd in __NSFireDelayedPerform ()
#10 0x01a03976 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#11 0x01a03417 in __CFRunLoopDoTimer ()
#12 0x019667e0 in __CFRunLoopRun ()
#13 0x01965dd4 in CFRunLoopRunSpecific ()
#14 0x01965ceb in CFRunLoopRunInMode ()
#15 0x01ccb879 in GSEventRunModal ()
#16 0x01ccb93e in GSEventRun ()
#17 0x0050d38b in UIApplicationMain ()
#18 0x000033e0 in main (argc=1, argv=0xbffff5fc) at /Users/Hermann/AppDev/fcApp/fcApp/main.m:16

Ответы [ 4 ]

12 голосов
/ 09 февраля 2012

Есть еще способы получить EXC_BAD_ACCESS с ARC.Некоторые из них, с которыми я столкнулся

  1. Если вы делаете что-то, когда создаете объект, и он асинхронно вызывает вас обратно - вы должны обязательно где-то сохранить ссылку на него, иначе ARC будетотпустите это.Примером является UIImagePicker - вы не можете просто сделать локальную переменную выбора изображений и вызвать ее (и затем отпустить ее, когда она перезвонит вам) - вы должны создать свойство и удерживать его

  2. Если вы не всегда используете свойства, чтобы удерживать его, вы можете столкнуться с проблемой - ARC использует присутствие сильных и слабых, чтобы знать, что делать - если вы вместо этого используете ивар, выможет обмануть ARC (не уверен на 100% в этом).Простой способ убедиться, что вы этого не сделаете, - это использовать @synthesize var = _var вместо того, чтобы свойство и ivar имели одно и то же имя.Таким образом, если вы забудете self.var = obj и просто используете var = obj, он будет жаловаться.

  3. Я столкнулся с ошибкой в ​​жестах и ​​вкладках - представления вкладок не сохранилижесты, добавленные IB - я задокументировал это здесь

Сбой при использовании распознавателей жестов в StoryBoard

В этих случаях зомби должны помочь - такэто не помогает означает, что вы, вероятно, преждевременно не вызываете освобождение.Скорее всего, вы копаете память - я бы проверил все приведения и везде, где вы используете встроенные массивы или не объектные указатели, чтобы убедиться, что вы не выходите за пределы.Охранник Маллок может помочь

https://developer.apple.com/library/ios/#documentation/Performance/Conceptual/ManagingMemory/Articles/MallocDebug.html

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

Хорошо, наконец-то я понял - Нили.

Я пока не знаю, какая деталь была неправильной. Наконец, я обнаружил, что проблема связана с UITextView. Первоначально текстовое представление не предназначалось для редактирования. Но я хотел получать touch-события. поэтому я следовал одному из советов, данных здесь: (iPhone) Как обрабатывать прикосновения к UITextView? Я назначил self (подкласс UIViewController) в качестве делегата UITextView и едва реализовал протокол следующим образом:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
    [self userShow:nil]; //Within this method a subsequent UIViewController subclass/object is created and pushed.
    return FALSE;
}

- (BOOL)textViewShouldEndEditing:(UITextView *)textView{
    return TRUE;
}

- (void)textViewDidBeginEditing:(UITextView *)textView{
    return;
}

- (void)textViewDidEndEditing:(UITextView *)textView{
    return;
}


- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    return TRUE;
}

- (void)textViewDidChange:(UITextView *)textView{
    return;
}

- (void)textViewDidChangeSelection:(UITextView *)textView{
    return;
}

Намерение состояло в том, чтобы фактически избежать редактирования, но получить событие, когда пользователь касается области UITextView и вызывает некоторое действие. В этом случае был создан некоторый последующий контроллер представления и помещен в стек навигации. Это работало нормально, но через некоторое время, в некоторых случаях (!), Приложение зависало. Благодаря ответу Лу и его блогу я смог получить EXC_BAD_ACCESS намного ближе к вызову textViewShouldBeginEditing. Подобно более ранним попыткам обойти EXC_BAD_ACCESS, я закомментировал UITextView и вызвал контроллер представления для вызова с использованием некоторого другого элемента UIButton. (Просто быстрое временное решение) К счастью, это помогло. Приложение больше не зависало. Теперь я перейду к более сложной реализации, которая принесет тот же пользовательский опыт, но вызовет другой контроллер представления другим, но безопасным способом.

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

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

Похоже, у вас не установлена ​​точка останова исключения.XCode не создает один по умолчанию.Откройте Навигатор точек останова (cmd + 6), нажмите + в левом нижнем углу и выберите «Добавить точку останова» из всплывающего меню.Нажмите «Готово», и вы обнаружите, что теперь вы приблизились к проблеме.

Без этого вы часто обнаружите, что отладчик выдает вам main без подсказки в трассировке стека, каккак ты туда попал.

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

Попробуйте запустить приложение с помощью инструментов («Продукт»> «Профиль») и выберите шаблон «Утечки».Это может дать вам подсказки о том, где ошибка. Больше информации здесь

...