Разработка iPhone - ошибка EXC_BAD_ACCESS без трассировки стека - PullRequest
6 голосов
/ 22 января 2009

Вот мой случай: у меня есть таблица, показывающая контакты. Кнопка «Добавить» на панели навигации используется для загрузки другого представления для ввода данных. Это новое представление содержит изображения в заголовке таблицы, и каждая ячейка таблицы имеет либо UITextField , либо UITextView . Когда я нажимаю «Отмена», представление выскакивает и память освобождается.

Вот моя проблема: когда я открываю интерфейс «Добавить», задаю значение в любом из UITextField или UITextView и нажимаю «Отмена», чтобы вернуться к родительскому представлению, я получаю EXC_BAD_ACCESS ошибка. Когда я отслеживаю его, «Add Controller» правильно вызывает call, но после [super dealloc] , когда я нажимаю Continue, выдает эту ошибку. Только это, никаких следов, хотя я использую NSZombieEnabled. Когда я запускаю код с Инструментами, я не получаю никакой ошибки: (

Надеюсь, я ясно объясню проблему. Есть указатели? Спасибо.

Ответы [ 6 ]

8 голосов
/ 22 января 2009

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

Всякий раз, когда я получаю сообщение об ошибке EXC_BAD_ACCESS, моя первая рекомендация - пройтись по коду, чтобы определить, какая строка вызывает его, а затем искать любые явные [object release] вызовы, которые ссылаются на этот объект. Прокомментируйте их один за другим, чтобы выяснить, где вы могли ошибиться (и, конечно же, убедитесь, что объект правильно отпущен позже).

Если линия не помогает вам определить, какие объекты являются причиной проблемы, начните просматривать вызовы [object release] и убедитесь, что вы не выпускаете объекты слишком много раз случайно, или освобождение объектов, которые вам не принадлежат.

Это приводит к хорошему общему руководству относительно release в Objective-C:

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

(Через Управление памятью с помощью Objective C / Cocoa / iPhone , в котором также есть несколько полезных советов.)

6 голосов
/ 30 ноября 2010

Хотя это чаще всего результат неправильного управления памятью, это может происходить по другим причинам (и его сложнее отладить, чем просто включить NSZombieEnabled). Например, если вы не ввели правильное количество аргументов в строку формата (т.е. при отладке другой проблемы с помощью NSLog), вы могли бы в итоге не отслеживать трассировку стека, даже если все аргументы отладки включены. К счастью, вы можете использовать GDB в Xcode, чтобы восстановить трассировку стека до предыдущего состояния .

В консоли GDB вы должны увидеть инструкцию, которая вызвала сбой вашей программы. Найдите последнюю успешную инструкцию возврата перед той, которая не удалась. Это должно выглядеть примерно так:

je    0x986cef35 <objc_msgSend+117>

Запишите шестнадцатеричное значение и выполните в GDB следующее:

set $eip = 0x986cef35
stepi
where

Теперь вы должны (надеюсь) получить более информативную трассировку стека.

Источник (аналогично ссылке выше)

4 голосов
/ 01 мая 2015

Ответ Кэмерона Спикерта несколько устарел, поскольку Xcode теперь использует lldb вместо gdb. Ссылка на исходную статью также не работает.

То же самое можно сделать довольно просто с помощью следующей команды lldb:

(lldb) thread backtrace

Это покажет bt для текущего потока. Если вы хотите изменить поток, из которого хотите получить bt, выберите фрейм и получите его так:

(lldb) thread list
(lldb) thread select 2
(lldb) thread backtrace

Если вы хотите повторить точное поведение ответа Камерона Спикерта, используйте следующие команды:

(lldb) expr unsigned int $eip = 0x1979c81d4
(lldb) stepi
(lldb) thread backtrace

Источник 1

Источник 2

3 голосов
/ 18 июня 2010

Поместите [super dealloc] в качестве последнего утверждения метода класса dealloc. Вы получите такое поведение, когда сначала освободите суперкласс.

1 голос
/ 24 февраля 2011

Заявления выше о том, что вы не должны выпускать объекты NIB, противоречат Apple: см. здесь , где говорится, что объекты, для которых у вас есть выход, должны быть освобождены в dealloc, а также что вы должны обязательно установите для ссылки на объект значение nil впоследствии.

Отказ от ответственности: я новичок в программировании на iPhone, хотя программировал долгое время.

1 голос
/ 22 января 2009

Общее правило гласит, что всем, что вы создаете, вам нужно управлять (сохранять / освобождать). Все, что выходит из NIB, обычно не должно быть выпущено в коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...