Как получить строку исходного кода из трассировки стека в obj-c/ios
Я использую NSSetUncaughtExceptionHandler
для печати трассировки стека в локальный файл на iPhone, который будет отправлен на наш сервер в следующий раз, когда приложение запустится. Затем я могу проверить данные исключения и исправить ошибку.
В некоторых авариях у меня есть имя модуля и функция, которая выбрала исключение, это легко.
Но в основном у меня есть что-то вроде этого:
"4 libc++abi.dylib 0x35bba3c5 _ZL19safe_handler_callerPFvvE + 76",
"5 libc++abi.dylib 0x35bba451 _ZdlPv + 0",
"6 libc++abi.dylib 0x35bbb825 __cxa_current_exception_type + 0",
"7 libobjc.A.dylib 0x37bab2a9 objc_exception_rethrow + 12",
"8 CoreFoundation 0x3575a50d CFRunLoopRunSpecific + 404"
и, например, причина:
*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array
но у меня есть десятки массивов в моем приложении, поэтому мне нужна помощь, чтобы найти конкретную строку, которая выбрала исключение, используя данные, которые я получаю из трассировки стека.
Кто-нибудь знает хорошую статью/учебник от Apple или другой, где я могу научиться декодировать числа в трассировке стека, чтобы найти проблемную строку в исходном коде.
Спасибо заранее!
Ответы
Ответ 1
Я настоятельно рекомендую включить исключение Breakpoint в Xcode. Он прекратит выполнение вашего кода на точной строке, которая приведет к сбою вашего приложения. Поэтому вам не нужно беспокоиться о том, какая из причин массива аварии.
*** - [__ NSArrayI objectAtIndex:]: индекс 0 за пределами для пустого массива
Добавление контрольной точки исключения
- Перейдите в раздел "Точки останова" на Xcode
- Нажмите "плюс" в нижней части раздела.
- Выберите пункт "Добавить контрольную точку исключения"
![Exception BreakPoint]()
Ответ 2
Я не знаю, как получить номера строк из трассировки стека (пока), но в некоторых точках моего кода, где я хочу напечатать номер строки, я использовал следующий фрагмент кода:
NSLog(@"%s line=%d", __func__, __LINE__);
который даст следующий результат:
2013-04-01 00:16:46.393 MyApp[847:c07] -[AppDelegate application:didFinishLaunchingWithOptions:] line=29
Если вы знакомы с базой Log4J, я предлагаю взглянуть на структуру Lumberjack, которая оказывается очень полезной для меня в различных проектах.
https://github.com/robbiehanson/CocoaLumberjack
Хотя это не может напрямую ответить на ваш вопрос, это просто означает напоминание.
Ответ 3
Установите точку останова в блоке catch, как только поток кода остановится, вы можете использовать команды gdb, такие как 'bt'.
Ответ 4
Распечатайте трассировку стека, хранящуюся в исключении, т.е. [exception callStackSymbols]
или [exception callStackReturnAddresses]
. В журналах сбоев Apple с iOS 5 это отображается вверху как "Last Exception Backtrace".
То, что вы видите, это стек вызовов, когда исключение повторно выбрано, что будет происходить так же просто, как try...finally
. Я точно не знаю, почему Apple сделала это изменение (возможно, чтобы избежать ошибок в циклах цикла), но там вы идете.