私はlldbを初めて使用し、po [$eax class]
を使用してエラーを診断しようとしています。
UIに表示されるエラーは次のとおりです。
Thread 1: EXC_BREAKPOINT (code=EXC_i386_BPT, subcode=0x0)
入力したものと返されたものを含むlldbコンソールは次のとおりです。
(lldb) po [$eax class]
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940).
The process has been returned to the state before expression evaluation.
グローバルブレークポイント状態の切り替えはオフです。
実行しているコードがキャッチされていないMach例外をスローしたため、アプリが停止しています。 Machの例外は、MachカーネルのBSDシグナルに相当します。これは、macOSオペレーティングシステムの最低レベルを構成します。
この場合、特定のMach例外はEXC_BREAKPOINT
です。 EXC_BREAKPOINT
は、よくある混乱の原因です...名前に「ブレークポイント」という単語が含まれているため、デバッガーのブレークポイントであると人々は考えています。それは完全に間違っているわけではありませんが、例外はそれよりも一般的に使用されます。
EXC_BREAKPOINT
は、実際には、Machの下位層が特定の命令(トラップ命令)を実行したときにレポートするという例外です。このトラップ命令は、ブレークポイントを実装するためにlldbによって使用されますが、システムソフトウェアのさまざまなビットでassert
の代わりとしても使用されます。たとえば、Swiftは、配列の終わりを超えてアクセスした場合にこのエラーを使用します。これは、エラーの時点でプログラムを停止する方法です。デバッガーの外部で実行している場合は、これによりクラッシュが発生しますが、デバッガーで実行している場合は、このEXC_BREAKPOINT
停止理由で制御がデバッガーに返されます。
混乱を避けるために、デバッガーブレークポイントを実装するためにデバッグしているプログラムにlldbが挿入したトラップである場合、lldbは停止理由としてEXC_BREAKPOINT
を表示しません。代わりに常にbreakpoint n.n
と表示されます。
したがって、スレッドが停止理由としてEXC_BREAKPOINT
で停止している場合は、通常、プログラムで使用されているシステムライブラリで、ある種の致命的なエラーが発生したことを意味します。この時点でのバックトレースは、どのコンポーネントがそのエラーを引き起こしているかを示します。
とにかく、そのエラーが発生したので、po [$eax class]
を実行してeaxレジスタのclassメソッドを呼び出し、eaxレジスタの値のクラスを把握しようとしました。そのメソッドを呼び出すと(デバッグしているプログラムでコードが実行されます)、クラッシュが発生します。それがあなたが引用した「エラー」メッセージがあなたに伝えていたものです。
これは、$eax
が有効なObjCオブジェクトを指していないため、ほぼ確実です。そのため、ランダムな値でメソッドを呼び出しているだけで、クラッシュします。
64ビットプログラムをデバッグしている場合、$ eaxは実際にはレジスタを渡す実際の引数の下位32ビット($ rax)であることに注意してください。 64ビットポインタの下位32ビットが有効なポインタ値である可能性は低いため、class
を呼び出すとクラッシュすることはまったく驚くべきことではありません。
64ビットIntelで最初に渡された引数(ObjCメソッドのself)でクラスを呼び出そうとした場合、本当にやりたかったのです。
(lldb) po [$rax class]
$rax
は関数の開始時にself
のみを保持するため、これも機能する可能性が低いことに注意してください。その後、スクラッチレジスタとして使用されます。したがって、関数への何らかの方法がある場合(コードが致命的にいくつかのテストに失敗したという事実がありそうです)、$ raxがまだself
を保持する可能性は低いでしょう。
また、これが32ビットプログラムの場合、$eax
は実際には引数の受け渡しには使用されません。32ビットのIntelコードは、レジスタではなくスタックで引数を渡します。
とにかく、何が悪かったのかを理解するために最初にすべきことは、この例外が発生したときにバックトレースを出力し、このエラーが発生したときに実行されていたコードを確認することでした。
同じ問題に苦しんでいて、この解決策がどこにも見つからなかったので、解決策を追加しています。
私の場合、Product-> Clean Build Folder(Clean + Optionキー)を実行して、プロジェクトを再構築する必要がありました。ブレークポイントとlldbコマンドが正しく機能し始めました。
プロジェクトをクリーンアップしてXcodeを再起動するとうまくいきました。