Подтвердить что ты не робот

Исключение отладки в Objective C и XCode

Я давно разработчик Microsoft, и я новичок в разработке iPhone, используя XCode. Итак, я читаю книгу и просматриваю примеры, пытаясь научить себя писать приложение iPhone с помощью Objective-C. Тем не менее, все было хорошо, однако время от времени я запускаю общее сообщение objc_exception_throw во время выполнения. Когда это произойдет, источник этого исключения очень сложно найти. После некоторых проб и ошибок я нашел свой ответ. Один из параметров был опечатан.

Как вы можете видеть ниже, я ошибся с параметром "otherButtonTitles", оставив вторую кнопку "t" в кнопке.

UIAlertView *alert = [[UIAlertView alloc] 
                      initWithTitle:@"Date and Time Selected" 
                      message:message 
                      delegate:nil
                      cancelButtonTitle:@"Cancel"
                      otherButonTitles:nil];

Причина, по которой мне пришлось найти время, - это то, что код успешно создан. Это нормальное поведение для компилятора Objective-C? Я привык к сбою сборки в компиляторе .NET, когда я делаю общую синтаксическую ошибку, подобную этой. Есть ли параметр компилятора, который я могу изменить, чтобы сделать встроенный сбой, когда я делаю эти ошибки?

4b9b3361

Ответ 1

Прежде всего, откройте ~/.gdbinit (файл .gdbinit в вашем домашнем каталоге - да, начинается с точки) и поместите его в него:

fb -[NSException raise]
fb objc_exception_throw
fb malloc_error_break

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

Затем откройте панель Get Info в своем проекте (или выберите свой проект (верхний элемент в Groups & Files) и нажмите cmd-i), перейдите на вкладку Build и установите для проекта Base SDK значение Device - iPhone OS [someversion]. Прокрутите до конца и найдите раздел GCC 4.0 - Warnings. Там; включите столько предупреждений, сколько вам удобно, но обязательно включите Treat Warnings as Errors (это эквивалент GCC_TREAT_WARNINGS_AS_ERRORS). Лично я решил:

Параметры настройки предупреждения GCC http://lhunath.lyndir.com/stuff/gcc_warnings.png

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

Вы также должны изучить NSZombie*. Это переменные среды, которые очень удобны для раннего взлома при неправильном распределении памяти или доступе. Например; wih NSZombieEnabled ничто действительно не будет выпущено; на dealloc он будет перезаписан с помощью _NSZombie, и если вы попытаетесь снова получить доступ к этой освобожденной памяти (разыменовывая освобожденный указатель), вы получите что-то, что нужно разбить в GDB, вместо того, чтобы вызов проходил, как обычно, только выдается по случайным данным (что, конечно, не то, что вы хотели). Для получения дополнительной информации об этом см. http://www.cocoadev.com/index.pl?NSZombieEnabled.

Ответ 2

Всегда используйте параметр -Werror GCC (GCC_TREAT_WARNINGS_AS_ERRORS = YES). У вас никогда не должно быть предупреждений в коде, и это пример, когда предупреждение является критичной ошибкой.

Кроме того, если вы получите objc_exception_throw, переключитесь на консоль (Command-shift-R) и найдите первый "низкий" номер.

2009-04-01 13:25:43.385 CrashExample[41720:20b] Stack: (
    2528013804,
    2478503148,
    2528036920,
    2528053460,
    2358032430,
    11076,
    11880,
    816174880,
    345098340,
    145973440,
    816174880,
)

В этом случае это будет "11076". Введите тип консоли:

info line *11076

Это скажет вам строку в вашем коде, где было исключено исключение.

Ответ 3

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

Кроме того, когда я сталкиваюсь с неперехваченным исключением, иногда полезно перейти в консоль gdb (должен появиться при выполнении вашего приложения) и ввести следующее для получения обратных трасс для всех потоков:

t a a bt

Ответ 4

То, что вы сделали, не является ошибкой времени компиляции, поскольку среда выполнения Objective-C проверяет во время выполнения, если объект может ответить на отправленное ему сообщение.

Я рекомендую добавить этот параметр сборки в свою цель или проект:

GCC_TREAT_WARNINGS_AS_ERRORS = YES

Ответ 5

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

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