objc_exception_throw
では、私のブレークポイントがちょうどトリガーされたと想像してください。デバッガー プロンプトの前に座って、例外オブジェクトに関する詳細情報を取得したいと考えています。どこで見つけますか?
4 に答える
例外オブジェクトは、最初の引数として に渡されますobjc_exception_throw
。LLDB は、正しい呼び出し規則で引数を参照するための$arg1
..$argn
変数を提供し、例外の詳細を簡単に出力できるようにします。
(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
objc_exception_throw
これらのコマンドを実行する前に、必ずコール スタックでフレームを選択してください。WWDC15 セッション ビデオの「Advanced Debugging and the Address Sanitizer」を参照して、これがステージで実行される様子を確認してください。
古い情報
GDB を使用している場合、最初の引数を参照する構文は、実行しているアーキテクチャの呼び出し規約によって異なります。実際の iOS デバイスでデバッグしている場合、オブジェクトへのポインターは register にあり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、64ビット)では、例外フレームで使用するxcode 6 im:objc_exception_throw
po $rax
32 ビット:
po $eax
ラックスとは?
Rax は、古い eax を置き換える 64 ビット レジスタです。
すべてのレジスタを見つける方法は?
register read
これを書いている時点で、この投稿はlldb print exceptionに対する私の Google ヒットのトップです。したがって、lldbとx86_64を説明するためにこの回答を追加しています。
を使用して例外を見つけようとしてpo $eax
失敗しましerror: Couldn't materialize struct: Couldn't read eax (materialize)
た。以前の回答からのリンクされたドキュメントに記載されている他の試みも失敗しました。
objc_exception_throw
重要なのは、最初にメイン スレッドのフレームをクリックする必要があることでした。lldbはそのフレームで開始しません。
私のすべての検索と次の例で、このブログエントリは、私にとってうまくいった方法で物事を説明した最初のエントリでした. 2012 年 8 月に投稿された、より現代的なものです。
catch ステートメントがある場合は、そこにブレークポイントを配置すると、その時点で例外オブジェクトを調べることができます。
catch ステートメントがない場合は、続行します。
端末に次のようなメッセージが表示されます。
キャッチされない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。理由: ' * -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: オブジェクト [0] から nil オブジェクトを挿入しようとしています'
ただし、アプリケーションが終了すると素敵なスタック トレースが失われるため、続行せずに検査する方法を探している可能性があります。
そのためには、Fnordの答えが最善のように思えますが、LLDBで動作させることができませんでした.