Главная iPhone Mac OS X Форум О себе

Отладка приложений в XCode

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

Как вы уже поняли из вступления, отлаживать нужно уметь и нужно уметь делать это хорошо. Частично качество этого процесса зависит от квалификации программиста, отчасти — от IDE и удобства и широты возможностей предоставляемого ею отладчика. XCode комплектуется отладчиком, удовлетворяющим всем предъявленным выше требованиям. С его помощью процесс отладки становится интуитивно простым и одновременно мощным, позволяющим свести количество прогонов программы с целью поиска мест ошибок к минимуму.

Прежде чем приступить к отладке программы ее необходимо скомпилировать с соответствующим ключом. Убедитесь, что на панели проекта в XCode выбрана опция компилятора Debug, а не Release. Такая опция содержит свой набор ключей для компилятора gcc, который является основным компилятором для построения исполняемых приложений в Mac OS.

Режим отладки

В момент построения программы компилятор, используя переданный набор ключей, кроме сборки приложения создает отдельный файл формата DWARF, содержащий отладочную информацию.

Всего существует 4 возможных варианта отладки. Разберём их все по очереди.


Отладка в редакторе

Весь процесс по отладке приложения можно вести непосредственно в текстовом редакторе XCode: устанавливать точки останова, просматривать значения переменных и управлять процессом выполнения приложения.

Отладка в редакторе

На пробу возьмите любое ваше приложение или исходники любой программы из комплекта примеров с сайта developer.apple.com, и установите в нескольких местах точки останова. В редакторе это можно сделать кликнув по пустому полю напротив строки, где желаете прервать выполнение программы. Точка останова будет помечена синей стрелкой. Повторное нажатие на стрелку сделает точку остановки неактивной.

Установка breakpoint

Запустите приложение в режиме отладки. Для этого выберите в меню Run->Debug или нажмите сочетание клавиш Cmd+Opt+Y. Дождитесь пока выполнение программы не остановится на одной из выставленных вами точках останова. При этом вы возвратитесь в окно проекта в XCode, дополненное панелью отладчика в верхней части окна редактора.

Панель отладки в редакторе

  • Список потоков. Необходим для переключения между тредами при отладке многопоточного приложения.
  • Breakpoints. С помощью этого переключателя можно активировать и деактивировать все доступные в приложении точки останова.
  • Continue. Эта кнопка продолжает выполнение приложение с места остановки.
  • Step over. Отладчик выполняет текущую строчку программы и останавливается.
  • Step in. Отладчик переходит в режим пошаговой отладки указанного в текущей строке метода, если для него доступны исходные тексты.
  • Step out. Отладчик выполняет оставшиеся в текущем методе команды и переходит в файл, откуда был вызван текущий метод.
  • Консоль отладчика. Открывает консоль для управления процессом отладки через командную строку.
  • Стек вызовов. Представляет собой указание последовательности вызовов методов в приложении, приведшей к вызову текущего метода. Можно выбрать один из методов в указанном списке и переместиться в точку, где остановилось его выполнение.

Стек вызовов

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

Всплывающее окно со значениями переменной

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

Контекстное меню

В процессе работы программы можно также менять значения переменных, пользуясь всплывающим окном.

Изменение значения переменной во всплывающем окне

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

Continue to here

Continue to here. Выполнение программы продолжится до указанной строки.

Step over

Step over. Отладчик выполняет текущую строчку программы и останавливается.

Step in

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

Отладка при помощи миниотладчика

Окно миниотладчика вызывается из меню Run->Mini Debugger и доступно только во время работы программы. Оно выглядит довольно аскетично, предоставляет минимальное число действий и всегда находится поверх всех окон.

Окно миниотладчика

При остановке работы программы окно миниотладчика раскрывается с исходным текстом на месте останова. Работа с ним эквивалентна работе с отладчиком в редакторе, описанном выше, с единственной разницей — исходники редактировать нельзя.

Окно миниотладчика распахнуто


Отладка в отладчике

Как бы странно ни звучал заголовок, но этот способ отладки является самым информативным из всех представленных и самым мощным по своим возможностям. Отладка программы ведётся в отдельном окне, вызываемом из меню Run->Debugger или с сочетанием клавиш Cmd+Shift+Y.

Окно отладчика

Набор кнопок эквивалентен кнопкам на панели отладчика в редакторе, дополненный парой новых действий.

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

Стек вызова

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

Дамп памяти для метода без исходных текстов

Список переменных может состоять, в зависимости от места исполнения программы, из трех групп: arguments, locals и global.

Список переменных

Группа Arguments представляет собой список переменных переданных в метод, который в данный момент выделен в стеке вызовов. Locals — это набор локальных переменных, объявленых в текущем методе. Globals представляет собой список глобальных переменных из доступных в системе библиотек. По умолчанию он пустой, но его можно пополнить, кликнув по треугольнику рядом с названием группы (это можно сделать только во время выполнения программы).

Стобец Value в списке переменных содержит значение переменной. Если она была изменена с момента последней остановки программы или в результате ручного изменения, ее значение становится красным.

Измененные значения переменных подсвечены красным цветом

Изменить значение переменной в процессе выполнения программы можно дважды кликнув по этому полю.

Изменение значения переменной по время работы программы

Столбец Summary несет дополнительную информацию о переменной: это может быть описание или представление значения переменной в строковом виде.

Столбец суммарной информации по переменной

В последнем случае вы можете изменить формат представления данных дважды кликнув по столбцу Summary или выбрав в меню Debug > Variables View > Edit Summary Format. Подробно способах форматирования можно узнать со страницы Using Data Formatters.

Отладчик также позволяет следить за определённой переменной и при изменении ее значения останавливать выполнение программы. Эту функцию можно применить к любой из перечисленных в списке переменной. Для этого нажмите правой кнопкой мыши на имя переменной и выберите пункт Watch variable. Рядом с именем отслеживаемой переменной появится значок лупы.

Слежение за переменной

Если при дальнейшей работе приложения значение переменной изменится, программа будет прервана с соответствующим сообщением.

Отслеживаемая переменная изменила значение

Отладка при помощи консоли

Весь процесс отладки, что я описал выше, на самом деле проходит через консольный отладчик gdb, а XCode скрывает от нас отправку команд в gdb под красивым графическим интерфейсом. Вызвать консоль отладки можно через меню Run->Console, а также с помощью одноименной кнопки на панели отладки.

Консоль

Полный список команд и основы работы с gdb можно узнать на странице Debigging with GDB.

Пример работы с gdb через консоль

Иногда бывает необходимо знать какие этапы в процессе выполнения приложения уже пройдены или требуется получать распечатки значений переменных в процессе работы программы. Для этих целей может сослужить хорошую службу метод NSLog. Требуется лишь выставить в желаемых местах программы его вызов, и указанная в параметрах строка будет выведена в консоль. Временами подобный вариант оказывается куда эффективнее, чем расстановка точек останова на всем пути выполнения программы.


NSLog(@"NSLog writes directly to the console!");

NSLog пишет сообщения в консоль


Список точек останова

При отладке большой по объёмам программы становится трудно ориентироваться и помнить все места, где были расставлены точки останова. Для этих целей в XCode существует отдельное окно, вызываемое через меню Run->Show->Breakpoints или сочетанием клавиш Cmd+Opt+B.

Список точек останова

С помощью этого окна можно управлять списком точек останова: удалять, деактивировать, изменять условия их работы. Последнему служит поле Condition, содержащее условие, при котором выполнение приложения будет остановлено в данной точке. При этом первый раз, вне зависимости от выполнения данного условия, приложение будет остановлено на каждой точке останова. Условие считается выполненным, если значение, описанное в нем, является истинным или отличным от нуля.

Условие срабатывания точки останова

Подобное условие можно выставить и в окне текстового редактора, нажав правой кнопкой по значку точки останова и выбрав Show Message Bubble.

Условие срабатывания точки останова в XCode

За каждой точкой останова можно закрепить определенное действие. Например, отправку команды отладчику или звуковой сигнал. Для этого нажмите треугольничек в строке с выбранной точкой останова и, выбрав желаемое действие из выпадающего списка, настройте его согласно вашим целям.

Действие связанное с точкой останова

Под конец хочу упомянуть, что существует преднастроенный набор точек останова с их действиями. Желаемое действие выбирается из контекстного меню.

Встроенные точки останова с действиями

Дополнительная информация:

Комментарий

Комментарии

venture 20.10.2008 14:41

спасибо за статью. иногда возникают проблемы при обработке breakpoint’ов. Отлатчик просто игнорирует расставленные брейкпоинты. После очистки кэша и полной перезагрузки xcode снова вроде начинает работать. Сталкивались ли вы со схожей проблемой?

ответить
Evgeniy Krysanov 20.10.2008 14:46

Да, сталкивался. Достаточно еще раз пересобрать (rebuild) приложение через Cmd+B. При это “переиндексируются” все точки останова.

ответить
nynja 20.10.2008 18:20

Тоже вопрос по брекпойнтам. в функциях dealloc почему-то никогда не останавливается. Просто программа завершается и все. И еще — как можно проверить приложение на наличие утечек памяти (проект под iPhone)

ответить
Evgeniy Krysanov 20.10.2008 23:56

Цитата из официальной документации:

Note that when an application terminates, objects may not be sent a dealloc message since the process’s memory is automatically cleared on exit—it is more efficient simply to allow the operating system to clean up resources than to invoke all the memory management methods.

Это значит, что при полном выходе из приложения (нажатии на кнопку Home) память из-под программы высвобождается целиком, а не происходит вызов dealloc для каждого объекта, потому breakpoint и не срабатывает в dealloc. Но если освобождение объекта происходит во время работы приложения, но dealloc вызван будет и точка останова в нем сработает.

Проверить приложение на утечки можно запустив программу в XCode через Run->Start with performance tool->Leaks, но я еще не разбирался в его работе, так что посоветовать дельного ничего пока не смогу.

ответить
mozilla 20.10.2008 15:14

Спасибо за статью и ссылки в конце. Очень полезный материал.

ответить
Tirex 22.10.2008 18:59

Отличная статья.

ответить
Maxim 4.12.2008 20:02

Здравствуйте! Как я понял, статья о том чтобы дебажить прогу на симуляторе. Скажите а получалось ли у вас дебажить сам девайс? У меня как-то получалось, но в основном (и сейчас тоже) приложение просто не запускается (висит черный экран), а xcode говорит: GDB: Running… Что с этим делать — не знаю. Может кто подскажет?

Кстати вычитал, на каком-то английском форуме, что чтобы точки останова гарантированно работали надо проделать следущее: xcode->preferences->debugging->Symbol loading options выключить галочку напротив Load symbols lazily

ответить
Alena 7.09.2011 13:27

Здравствуйте, Maxim. Проверьте совпадает ли iOS версия на дивайсе и iOS версия, под которую вы собираете билд, который пытаетесь запустить по дебагом. Если они не совпадают, тогда не удивительно, что вы видите черный экран.

ответить

Форма комментирования для «Отладка приложений в XCode»

Обязательное поле. Не больше 30 символов.

Обязательное поле

captcha image Пожалуйста, введите символы, которые вы видите на изображении

Maxim 7.09.2011 13:44

Спасибо Alena, уже неактуален мой вопрос (я не помню уже как его успешно решил), однако хотелось бы заметить что я собираю продукт под SDK 4.3 и успешно его дебажу под устройством 3.1.3 Главное чтобы iOS Deployment Target стоял нужный.

ответить
.