Xcode / LLDB: как получить информацию об исключении, которое только что было вызвано?
хорошо, так что представьте, что моя точка останова в objc_exception_throw
только что вызвал. Я сижу в приглашении отладчика, и я хочу получить дополнительную информацию об объекте исключения. Где я могу его найти?
4 ответа:
объект исключения передается в качестве первого аргумента
objc_exception_throw
. Символы отладки обеспечивает$arg1
..$argn
переменные для ссылки на аргументы в правильном соглашении о вызове, что упрощает печать сведений об исключении:(lldb) po $arg1 (lldb) po [$arg1 name] (lldb) po [$arg1 reason]
выберите
objc_exception_throw
фрейм в стеке вызовов перед выполнением этих команд. См. раздел "Расширенная отладка и дезинфицирующее средство адреса" в видеороликах сеанса WWDC15, чтобы увидеть, как это выполняется ступень.Устаревшая Информация
если вы находитесь на GDB, синтаксис для ссылки на первый аргумент зависит от соглашений о вызовах архитектуры, на которой вы работаете. Если вы выполняете отладку на реальном устройстве iOS, указатель на объект находится в регистре
r0
. Чтобы распечатать его или отправить сообщения, используйте следующий простой синтаксис:(gdb) po $r0 (gdb) po [$r0 name] (gdb) po [$r0 reason]
на симуляторе iPhone все аргументы функции передаются в стек, поэтому синтаксис значительно более ужасен. Самое короткое выражение, которое я мог построить, что попадает в него
*(id *)($ebp + 8)
. Чтобы сделать вещи менее болезненными, я предлагаю использовать переменную удобства:(gdb) set $exception = *(id *)($ebp + 8) (gdb) po $exception (gdb) po [$exception name] (gdb) po [$exception reason]
вы также можете установить
$exception
автоматически всякий раз, когда точка останова запускается путем добавления списка команд вobjc_exception_throw
точка останова.(обратите внимание, что во всех случаях я тестировал, объект исключения также присутствовал в
eax
иedx
регистрирует момент останова удар. Хотя я не уверен, что так будет всегда.)добавлено из комментария ниже:
на lldb выберите кадр стека для
objc_exception_throw
и затем введите следующую команду:(lldb) po *(id *)($esp + 4)
на новых симуляторах (iOS 8, 64bit) Xcode 6 im использует в кадре исключения:
objc_exception_throw
po $rax
в 32 бит:
po $eax
что такое rax?
Rax-это 64-битный регистр, который заменяет старый eax
как найти все регистры?
register read
на момент написания этой статьи этот пост является моим лучшим хитом Google для: исключение печати lldb. Таким образом, я добавляю этот ответ к учетной записи lldb и x86_64.
мои попытки найти исключение с помощью
po $eax
не сerror: Couldn't materialize struct: Couldn't read eax (materialize)
. Другие попытки, описанные в связанных документах из предыдущих ответов, также потерпели неудачу.ключ был я должен был сначала нажать на
objc_exception_throw
кадр в моем главном потоке. lldb не начинается в этом рамка.во всех моих поисках и следующих примерах,эта запись в блоге был первым, чтобы объяснить вещи таким образом, что работал для меня. Это более современный, будучи размещены в августе 2012 года.
Если у вас есть оператор catch, поместите туда точку останова, и вы можете проверить объект исключения в этой точке.
Если у вас нет оператора catch, продолжайте.
вы получите сообщение в вашем терминале, как это:
завершение приложения из-за неперехваченного исключения 'NSInvalidArgumentException', причина: '* - [__NSPlaceholderDictionary initWithObjects:forKeys: count:]: попытка вставить нулевой объект из объекты[0]'
, вы, вероятно, ищете способ проверить его без продолжения, так как вы потеряете свою хорошую трассировку стека, когда приложение будет завершено.
для этого похоже, что ответ Fnord лучше всего, но я не смог заставить его работать в LLDB.