こんにちは この記事では、iPhoneおよびMacのアプリケーションをデバッグするときに、どのようにすれば人生を楽にすることができるかについてお話します。 これは、EXC_BAD_ACCESS例外のデバッグに関するものです。EXC_BAD_ACCESS例外は、最も不快なものの1つです。
EXC_BAD_ACCESS例外は、既にリリースされているオブジェクトにメッセージを送信しようとすると発生します。 エラーが発生するまでに、コールスタックに役立つ情報が含まれていないため、状況は通常複雑です。 つまり、どの特定のオブジェクトがリリースされたかは明確ではありません。 さらに、コードがどこでリリースされたかは明らかではありません:)。 アプリケーションがマルチスレッドである場合、さらに楽しくなります。
幸いなことに、
Appleのスタッフは私たちを助けるために最善を尽くしました。 彼らはスタブクラス
NSZombieを作成しました。 サポートを有効にした場合(これを行う方法を説明します)、その場所(つまり、メモリ内のアドレス)で各オブジェクトを削除した後、ゾンビは生きてメッセージを受信します。これにより、デバッグ中のオブジェクトを判別できます。リリースしてエラーを修正します。
それでは始めましょう。 ある日、iPhoneまたはMacアプリケーションがクラッシュし始め、デバッガーコンソールに次のメッセージが表示されます。
プログラム受信信号:「EXC_BAD_ACCESS」。
そして、実際には、これ以上何もありません。 おそらく、コールスタックも役に立ちませんでした。
[
グループとファイル]ウィンドウ(
xCodeの左側)で、[
実行可能 ファイル]ブランチを見つけます。 アプリケーションの実行可能ファイルを右クリックし、ドロップダウンメニューから[
情報を見る]を選択します。 表示されるウィンドウで、「
引数」タブを開き、
NSZombieEnabledおよび
MallocStackLoggingNoCompactの 2つの環境変数を追加します。
NSZombieEnabledを
YESに設定し、
MallocStackLoggingNoCompactを
1に設定します。 どのように見えるかはスクリーンショットに示されています:
ここで、アプリケーションを実行し、エラーを再現するために必要な手順を繰り返します。 デバッガコンソールで、
EXC_BAD_ACCESSを報告する代わりに
、次のようなものが表示されるはずです。
2010-01-25 14:35:24.840 MyApplication[1393:20b] *** -[CFString retain]: message sent to deallocated instance 0x42a5060
これは、アドレス
0x42a5060にクラス
CFStringのオブジェクトがあったことを意味します。 彼はすでに釈放されており、あなたのプログラムは満足しておらず、メッセージ
retainを彼に送ろうとしています。 このオブジェクトを見つけ、コード内で追加の
リリースが呼び出された場所を見つけることは残っています。 どちらの
リテインも呼び出されず、特定の状況に依存します:)
以下が役立ちます。デバッガーコンソールで、次のコマンドを入力します。
shell malloc_history 1393 0x42a5060
1393の代わりに、プロセスID(PID)を入力する必要があります。 アプリケーション名の直後のコンソールエラーメッセージで確認できます。 0x42a5060の代わりに、解放されたオブジェクトのアドレスを入力します(エラーメッセージでも確認できます)。
その結果、あなたの目は次のような恐ろしい絵を見ます:
心配しないで、すべてが一見したように怖いものではありません。 近いうちに、コードに存在するクラスとメソッドの名前を探します。 つまり、あなたによって書かれました。 どこかで悪意のある
リリースコールを隠しました。 検索して修正します。
PS私の目の前で、Instruments / ObjectAllocを使用してそのようなエラーをキャッチできることをどこかで読みました。 誰かが私にウォッカをくれたらとても感謝しています...ああ、ヒント