2009-01-22 2 views
6

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

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

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

+0

проблема волшебно исчезает, когда я удаляю [освобождение] Tableview из моего «Добавить контакт». Метод dealloc класса контроллера. Но я должен освободить объект tableView, не так ли? Хотя я использую файл nib - и сделал tableView 'IBOutlet'. – Mustafa

+1

Нет, не стоит. Правило, которое нужно запомнить: «Если вы явно не выделили, не скопировали или не сохранили его, то вы явно не освободите его». –

ответ

8

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

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

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

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

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

(Via Memory Management with Objective C/Cocoa/iPhone, который также имеет некоторые хорошие советы.)

1

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

3

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

6

Хотя это чаще всего является результатом неправильной памяти, это может произойти по другим причинам (и сложнее отлаживать, чем просто включить NSZombieEnabled). Например, если вы не указали правильное количество аргументов в строку формата (т. Е. При отладке другой проблемы с NSLog), вы можете завершить трассировку стека даже при включенном аргументе отладки. К счастью, вы можете использовать GDB в Xcode до restore the stack trace to a previous state.

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

je 0x986cef35 <objc_msgSend+117> 

Примечание шестнадцатеричное значение и выполнить следующие действия в GDB:

set $eip = 0x986cef35 
stepi 
where 

Вы должны (я надеюсь), имеют более информативный стека в настоящее время.

Source (такой же, как по ссылке выше)

+0

[ссылка] (http://www.mulle-kybernetik.com/weblog/2010/07/exc_bad_access_and_no_stack_tr.html) не работает. Вот [обновлено] (http://www.mulle-kybernetik.com/weblog/2010/exc_bad_access_and_no_stack_tr.html) – BLC

1

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

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

2

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

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

(lldb) thread backtrace 

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

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

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

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

Source 1

Source 2

Смежные вопросы