О runtime ошибке SIGABRT

Баг с текстом SIGABRT в NSLog может появляться при тестировании программы на iPhone Simulator. Например, при открытии нового View. То есть он возникает во время работы программы, а компилятор XCode не находит эту ошибку. На понимание причины бага или сигнала SIGABRT было потрачено 3-4 часа. Поэтому было решено написать эту статью. Посмотрим сначала, что нам пишет википедия об этой ошибке.

POSIX® (англ. Portable Operating System Interface for Unix — Переносимый интерфейс операционных систем Unix) — набор стандартов, описывающих интерфейсы между операционной системой и прикладной программой. Стандарт создан для обеспечения совместимости различных UNIX-подобных операционных систем и переносимости прикладных программ на уровне исходного кода, но может быть использован и для не-Unix систем.
В POSIX-системах, SIGABRT — сигнал, посылаемый процессом самому себе при выполнении функции abort(), для аварийного останова, в случае невозможности дальнейшего продолжения программы. Сигнал SIGABRT процесс посылает сам себе, когда вызывает функцию abort() (функция libc, с прототипом в stdlib.h). Сигнал SIGABRT может быть перехвачен или проигнорирован, но abort() принудительно завершит программу (предварительно сбросив и закрыв стандартные потоки и сделав дамп памяти программы) даже если этого не сделает обработчик сигнала. Таким образом, функция abort() гарантирует завершение программы, почему она часто используется библиотеками в аварийных ситуациях — когда выполнение не должно быть продолжено, но основная программа должна иметь возможность выполнить действия, необходимые перед аварийным завершением. Также SIGABRT вызвается утверждениями (англ. assertions; средство отладки Си — макроопределение assert() вызывает abort() если утверждение переданное в качестве аргумента ложно).

Из этого текста можно понять, что ошибка или сигнал SIGABRT посылается просто из-за вызова функции abort() при падении программы. В свою очередь эта функция может вызываться утверждением assert(), но мы не можем посмотреть и выявить точную причину бага. Поэтому SIGABRT – один из самых вредных и труднопреодолимых багов при разработке для iPhone: отладка(debugging) не помогает, так как ошибка возникает где-то в коде, который не доступен разработчику. В интернете можно прочитать много всего про этот баг приложений для iPhone. Кому-то помогла перезагрузка XCode каким-то магическим образом или “Clean all Targets”. Пишут также, что это ошибка XCode или Симулятора, а не ошибка разработчика. Я думаю, что проблема в другом.

Наверное, главная и самая распространенная причина этой ошибки(касательно iPhone, iPhone Simulator) в том, что XIB не соответствует вашим аутлетам(Outlets) или классам. Например, если написать:
@interface FavoritesTableView : UITableViewController,

когда у вас нет контроллера TableViewController, а вместо него обычный View с контролом TableView, то выскочит эта ошибка. Видимо, программа пытается обратиться к сущностям, которых нет, при загрузке View. Они либо были освобождены из памяти(deallocated) раньше времени, либо их просто нет (например, в XIB). Далее вызывается abort(), который посылает сигнал SIGABRT.

Итак, в данном случае надо было написать:
@interface FavoritesTableView : UIViewController

Также SIGABRT может быть вызван обращением к любой несуществующей сущности – к элементу за пределами массива, к переменной, объекту, XIB файлу и т.д.