Анализ аварийных журналов iOS.

Для того чтобы ваше приложение попала в Appstore его нужно как следует протестировать на наличие ошибок. Оно должна безупречно работать не только на конкретном устройстве, но и на всей «линейке» данных устройств (iPhone3, iPhone4, iPhone5 и iPad) и на выбранных операционных системах.
Но даже после того как оно попало в AppStore это не гарантирует, что программа написана без ошибок и в определенной ситуации может быть сбой в результате которого, как говорят пользователи, программа «вылетает».
При сбое создается так называемый аварийный журнал, но куда при этом смотреть не понятно.

Давайте определимся, что это за аварийный журнал и где его взять?
Когда приложение «падает», то есть аварийно завершает свою работу на устройстве iOS, операционная система создает отчет о сбое или аварийный журнал. Этот журнал сохраняется на устройстве.

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

Есть много способов, как получить аварийный журнал с устройства.
Устройство, которое синхронизируется с iTunes, хранит свои аварийные журналы на ПК. В зависимости от ОС, вот места, где их можно найти:
Mac OS X:
~/Library/Logs/CrashReporter/MobileDevice/

Windows XP:
C:\Documents and Settings\\Application Data\Apple Computer\Logs\CrashReporter\MobileDevice\

Windows Vista или 7:
C:\Users\\AppData\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice\

Если у тестора ваша программа «падает», вы можете попросить синхронизировать его устройство с iTunes, забрать в одном из вышеуказанных мест (в зависимости от ОС) журнал и отправить его вам по почте.

Вот как это выглядит на Mac OS X Lion в Finder-e.

Как вы можете видеть расширение у этого журнала — *.crash.

Об этом процессе хорошо написано на Хабрахабре в посте «Демистификация аварийных журналов iOS» - http://habrahabr.ru/post/167805.

Здесь пойдет речь о том, что если по каким-то причинам  журнал не может быть отправлен разработчику. А доступен только pdf файл этого журнала. Что делать в таком случае?

Недавно я столкнулся с такой проблемой: После локального тестирования и убеждения себя в том, что вроде бы все хорошо, собираю проект (AdHoc)  через Hudson. Тестировщик инсталлирует приложение себе на девайс, запускает и начинает тестировать. Спустя некоторое время получаю от него .crash репорт в формате .pdf и с описанием, где произошло “падение”. Пытаюсь воспроизвести – не выходит, у меня все работает при тех же исходных. Что делать? Во-первых, я зашел на testflightapp.com -> TestfLightLive и на вкладке “stability” посмотрел, есть ли crash log-и. Надо иметь в виду, что для работы с TestFlight нужно установить в приложение TestFlight SDK.

Вот пример такого лога:

Что можно из этого всего вынести?
Видно, что произошло исключение EXC_CRASH (SIGSEGV) в главной нити с индексом 0. Далее идет стек вызовов – путь, по которому приложение пришло к краху. Но почему при запуске под дебаггером тот же самый стек выглядит по-другому, и дебаггер даже показывает какой-то текст ошибки?

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

Давайте разберем, что из себя представляет запись стэка вызовов, например, вот эти:

Запись состоит из пяти колонок.
В первой колонке содержится порядковый номер записи. Важно знать, в каком направлении следует стек вызовов. Следует от от самого большого порядкового номера к нулю. То есть, вызов с нулевым порядковым номером  и есть причина падения, перед ней выполнялся вызов с номером 1, и т.д.
Во второй колонке содержится название фреймворка или системной библиотеки. Видимо, это таблица импорта присутствует всегда на девайсе, поэтому тут нет расхождения между логом девайса и симулятора. Далее следует абсолютный адрес точки входа функции (функция = вызов). Тут тоже пока сходится.
В третьем столбце находится адрес функции.
В четвертом находится адрес какого-то сегмента, вероятно, точка входа во фреймворк или библиотеку, а может быть адрес экземпляра класса. В логе симулятора на этом месте название функции.
Пятый столбец вероятно содержит смешение в байтах от начала фрейворка до машинной инструкции, которая вызвала исключение. Если сложить четвертый и пятый получим третий.
Задача – восстановить из абсолютных адресов название класса и метода, вызвавших крах.
Для восстановления названия функции вызвавший крах приложения  я попробовал стандартную утилиту командной строки atos (Address to Symbol). На вход ей дается имя бинарного файла и интересующий адрес, а на выходе получаем название класса, метода и номер строки в исходном коде.

Что нам для этого понадобится ? Во-первых dSYM-файл. Где его можно взять показано на скриншоте.

Получение DSYM-файла

Примечание: Вам нужно хранить код того build-а,  который в данный момент тестируется. Тут должно быть точное соответствие версий, в противном случае аварийный журнал не может быть полностью символизирован. Так делается если тестировщик не может прислать вам отчет в формате *.crash.

terminal

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий