Отладка приложений в XCode
Процесс отладки программ неотделим от процесса написания кода. Невозможно сесть и сразу написать более-менее серьёзное приложение и ни разу не ошибиться. Ошибаются все и это нормально — все мы люди. Но у обычных людей нет возможности вернуться назад, поменять что-то в своих действия и изменить своё решение — у программистов такая привилегия есть (безусловно, применительно к результатам их деятельность, а не к жизненным ситуациям) и они должны ею пользоваться, особенно когда от результатов их творчества зависит чья-то жизнь или такая мелочь как сохранение текущего места работы :)
Как вы уже поняли из вступления, отлаживать нужно уметь и нужно уметь делать это хорошо. Частично качество этого процесса зависит от квалификации программиста, отчасти — от IDE и удобства и широты возможностей предоставляемого ею отладчика. XCode комплектуется отладчиком, удовлетворяющим всем предъявленным выше требованиям. С его помощью процесс отладки становится интуитивно простым и одновременно мощным, позволяющим свести количество прогонов программы с целью поиска мест ошибок к минимуму.
Прежде чем приступить к отладке программы ее необходимо скомпилировать с соответствующим ключом. Убедитесь, что на панели проекта в XCode выбрана опция компилятора Debug, а не Release. Такая опция содержит свой набор ключей для компилятора gcc, который является основным компилятором для построения исполняемых приложений в Mac OS.
В момент построения программы компилятор, используя переданный набор ключей, кроме сборки приложения создает отдельный файл формата DWARF, содержащий отладочную информацию.
Всего существует 4 возможных варианта отладки. Разберём их все по очереди.
Отладка в редакторе
Весь процесс по отладке приложения можно вести непосредственно в текстовом редакторе XCode: устанавливать точки останова, просматривать значения переменных и управлять процессом выполнения приложения.
На пробу возьмите любое ваше приложение или исходники любой программы из комплекта примеров с сайта developer.apple.com, и установите в нескольких местах точки останова. В редакторе это можно сделать кликнув по пустому полю напротив строки, где желаете прервать выполнение программы. Точка останова будет помечена синей стрелкой. Повторное нажатие на стрелку сделает точку остановки неактивной.
Запустите приложение в режиме отладки. Для этого выберите в меню Run->Debug или нажмите сочетание клавиш Cmd+Opt+Y. Дождитесь пока выполнение программы не остановится на одной из выставленных вами точках останова. При этом вы возвратитесь в окно проекта в XCode, дополненное панелью отладчика в верхней части окна редактора.
- Список потоков. Необходим для переключения между тредами при отладке многопоточного приложения.
- Breakpoints. С помощью этого переключателя можно активировать и деактивировать все доступные в приложении точки останова.
- Continue. Эта кнопка продолжает выполнение приложение с места остановки.
- Step over. Отладчик выполняет текущую строчку программы и останавливается.
- Step in. Отладчик переходит в режим пошаговой отладки указанного в текущей строке метода, если для него доступны исходные тексты.
- Step out. Отладчик выполняет оставшиеся в текущем методе команды и переходит в файл, откуда был вызван текущий метод.
- Консоль отладчика. Открывает консоль для управления процессом отладки через командную строку.
- Стек вызовов. Представляет собой указание последовательности вызовов методов в приложении, приведшей к вызову текущего метода. Можно выбрать один из методов в указанном списке и переместиться в точку, где остановилось его выполнение.
Во время остановки работы приложения, вы можете подвести курсор мыши к любой переменной и увидеть в раскрывающемся окне ее значение и значения всех свойств, входящих в ее состав.
Клик по двойной стрелке рядом с любой переменной вызывает контекстное меню, с помощью которого можно в один щелчок напечатать содержимое данной переменной в консоли (о ней позже), переместиться в место объявления переменной, поглядеть представление значения выбранной переменной в памяти, посмотреть справку по указанному классу, а также изменить реакции и внешний вид окна с вышеуказанной информацией.
В процессе работы программы можно также менять значения переменных, пользуясь всплывающим окном.
Процессом выполнения программы также можно управлять не обращаясь к кнопкам на панели отладчика. Если подвести курсор мыши к началу строки, в зависимости от текущего места выполнения программы может появиться набор кнопок, нажатие на которые приведет к следующим действиям.
Continue to here. Выполнение программы продолжится до указанной строки.
Step over. Отладчик выполняет текущую строчку программы и останавливается.
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.
Иногда бывает необходимо знать какие этапы в процессе выполнения приложения уже пройдены или требуется получать распечатки значений переменных в процессе работы программы. Для этих целей может сослужить хорошую службу метод NSLog. Требуется лишь выставить в желаемых местах программы его вызов, и указанная в параметрах строка будет выведена в консоль. Временами подобный вариант оказывается куда эффективнее, чем расстановка точек останова на всем пути выполнения программы.
NSLog(@"NSLog writes directly to the console!");
Список точек останова
При отладке большой по объёмам программы становится трудно ориентироваться и помнить все места, где были расставлены точки останова. Для этих целей в XCode существует отдельное окно, вызываемое через меню Run->Show->Breakpoints или сочетанием клавиш Cmd+Opt+B.
С помощью этого окна можно управлять списком точек останова: удалять, деактивировать, изменять условия их работы. Последнему служит поле Condition, содержащее условие, при котором выполнение приложения будет остановлено в данной точке. При этом первый раз, вне зависимости от выполнения данного условия, приложение будет остановлено на каждой точке останова. Условие считается выполненным, если значение, описанное в нем, является истинным или отличным от нуля.
Подобное условие можно выставить и в окне текстового редактора, нажав правой кнопкой по значку точки останова и выбрав Show Message Bubble.
За каждой точкой останова можно закрепить определенное действие. Например, отправку команды отладчику или звуковой сигнал. Для этого нажмите треугольничек в строке с выбранной точкой останова и, выбрав желаемое действие из выпадающего списка, настройте его согласно вашим целям.
Под конец хочу упомянуть, что существует преднастроенный набор точек останова с их действиями. Желаемое действие выбирается из контекстного меню.
Дополнительная информация:
Комментарии
спасибо за статью. иногда возникают проблемы при обработке breakpoint’ов. Отлатчик просто игнорирует расставленные брейкпоинты. После очистки кэша и полной перезагрузки xcode снова вроде начинает работать. Сталкивались ли вы со схожей проблемой?
Да, сталкивался. Достаточно еще раз пересобрать (rebuild) приложение через Cmd+B. При это “переиндексируются” все точки останова.
Тоже вопрос по брекпойнтам. в функциях dealloc почему-то никогда не останавливается. Просто программа завершается и все. И еще — как можно проверить приложение на наличие утечек памяти (проект под iPhone)
Цитата из официальной документации:
Это значит, что при полном выходе из приложения (нажатии на кнопку Home) память из-под программы высвобождается целиком, а не происходит вызов dealloc для каждого объекта, потому breakpoint и не срабатывает в dealloc. Но если освобождение объекта происходит во время работы приложения, но dealloc вызван будет и точка останова в нем сработает.
Проверить приложение на утечки можно запустив программу в XCode через Run->Start with performance tool->Leaks, но я еще не разбирался в его работе, так что посоветовать дельного ничего пока не смогу.
Спасибо за статью и ссылки в конце. Очень полезный материал.
Отличная статья.
Здравствуйте! Как я понял, статья о том чтобы дебажить прогу на симуляторе. Скажите а получалось ли у вас дебажить сам девайс? У меня как-то получалось, но в основном (и сейчас тоже) приложение просто не запускается (висит черный экран), а xcode говорит: GDB: Running… Что с этим делать — не знаю. Может кто подскажет?
Кстати вычитал, на каком-то английском форуме, что чтобы точки останова гарантированно работали надо проделать следущее: xcode->preferences->debugging->Symbol loading options выключить галочку напротив Load symbols lazily
Форма комментирования для «Отладка приложений в XCode»
Здравствуйте, Maxim. Проверьте совпадает ли iOS версия на дивайсе и iOS версия, под которую вы собираете билд, который пытаетесь запустить по дебагом. Если они не совпадают, тогда не удивительно, что вы видите черный экран.
Спасибо Alena, уже неактуален мой вопрос (я не помню уже как его успешно решил), однако хотелось бы заметить что я собираю продукт под SDK 4.3 и успешно его дебажу под устройством 3.1.3 Главное чтобы iOS Deployment Target стоял нужный.