Xcode / LLDB: как получить информацию об исключении, которое только что было сгенерировано? - PullRequest
81 голосов
/ 25 июля 2010

ОК, представьте, что моя точка останова в objc_exception_throw только что сработала. Я сижу в приглашении отладчика и хочу получить больше информации об объекте исключения. Где я могу найти это?

Ответы [ 4 ]

156 голосов
/ 25 июля 2010

Объект исключения передается в качестве первого аргумента objc_exception_throw.LLDB предоставляет переменные $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 Simulator все аргументы функции передаются в стек, поэтому синтаксис значительно более ужасен.Самое короткое выражение, которое я смог построить, это *(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)
10 голосов
/ 30 сентября 2014

на новых симуляторах (iOS 8, 64bit) xcode 6 im, использующих в рамке исключения: objc_exception_throw

po $rax

в 32 бита:

po $eax

Что такое rax?

Rax - это 64-битный регистр, который заменяет старый eax

Как найти все регистры?

register read

Источник википедии

5 голосов
/ 10 апреля 2013

На момент написания этой статьи этот пост был моим самым популярным в Google: исключение lldb print . Таким образом, я добавляю этот ответ к аккаунту lldb и x86_64.

Мои попытки найти исключение с помощью po $eax окончились неудачей с error: Couldn't materialize struct: Couldn't read eax (materialize). Другие попытки, описанные в связанных документах из предыдущих ответов, также потерпели неудачу.

Ключ был в том, что я должен был сначала щелкнуть на рамке objc_exception_throw в моей основной ветке. lldb не начинается в этом кадре.

Во всех моих поисках и следующих примерах эта запись в блоге была первой, которая объяснила вещи таким способом, который работал для меня. Он более современный, опубликован в августе 2012 года.

0 голосов
/ 15 мая 2013

Если у вас есть оператор catch, поместите туда точку останова, и вы сможете проверить объект исключения в этой точке.

Если у вас нет оператора catch, продолжайте.

Вы получите сообщение в своем терминале, например:

Завершение приложения из-за необработанного исключения 'NSInvalidArgumentException', причина: '* - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: попыткичтобы вставить объект nil из объектов [0] '

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

Для этого кажется, что ответ Фнорда - лучший, но я не смог заставить его работать в LLDB.

...