macOS Finderのクラッシュレポートアラートを理解する方法

macOS Finderのクラッシュレポートアラートを理解する方法

クラッシュレポートは、macOSでアプリがクラッシュした原因を解明する手がかりとなることがあります。クラッシュレポートがMacについて実際に何を伝えているのかを理解する方法についてご紹介します。

Mac でアプリが予期せず終了したときに Finder の警告が表示されるのを見たことがあるでしょう。

プログラミングの世界では「クラッシュ」と呼ばれるこれらのエラーは、通常、システムやCPUが実行できない不正なコードが実行されたときに発生します。また、アプリが不足している、あるいは古いバージョンのライブラリやフレームワークにアクセスしようとして、必要なコードを実行できない場合にも発生することがあります。

macOS にこれらのクラッシュアラートのいずれかが表示された場合は、「無視」ボタンをクリックするか、「報告」ボタンをクリックすることができます。

「報告」ボタンをクリックすると、Finder にクラッシュレポートと「Apple に送信」ボタンが表示されます。エラーの原因が Apple 製ソフトウェアである場合は、レポートを Apple に送信してください。

各クラッシュレポートは、/Users/~/Library/Logs/ のユーザーフォルダ内の「DiagnosticReports」フォルダ内の .ips ファイルに保存されます。

また、コンソール ウィンドウの左側にある「クラッシュ レポート」項目を選択し、ウィンドウの右側にあるレポートを選択して、レポートを Control キーを押しながらクリックするか、レポートを右クリックして、ポップアップ メニューから「Finder で表示」を選択することで、Apple のコンソール アプリでこれらのレポートを表示して開くこともできます。

これにより、Finder の DiagnosticReports フォルダが開き、保存されているすべてのクラッシュレポートファイルが表示されます。これらのレポートは macOS によって一定期間のみ保存され、その後は古いものから自動的に削除されます。

選択したクラッシュ レポート ファイルをゴミ箱に移動する場合は、コンソール ポップアップ メニューに [ゴミ箱に移動] メニュー項目もあります。

Finderで.ipsファイルをダブルクリックすると、コンソールアプリで再度開きます。Finderで.ipsファイルをControlキーを押しながらクリックし、ポップアップメニューから「このアプリケーションで開く」を選択し、「テキストエディット」を選択すると、テキストエディットで.ipsファイルを開くこともできます。

.ips ファイルに保存される各レポートのテキストは JSON 形式であるため、理解するには JSON を読み取ることができる必要があることに注意してください。

コンソールでクラッシュレポートを読む

いずれにしても、コンソールでクラッシュ レポートを選択すると、その下のメイン テキスト ペインでそのテキストを読むことができます。

クラッシュレポートの最初のいくつかのフィールドを見てみましょう。UNIXにおける「プロセス」とは、実行中のアプリケーションを意味します。フィールドは以下のとおりです。

  1. プロセス - アプリまたはプロセスの名前。
  2. パス - アプリのバイナリがディスク上に存在する場所。
  3. 識別子 - 通常はバイナリ名またはバンドル名ですが、必ずしもそうとは限りません。
  4. バージョン - バイナリ バージョン、または不明な場合は ???。
  5. コード タイプ - Intel または Apple Silicon。両方の場合は「ユニバーサル」。
  6. 親プロセス - このプロセスを起動したバイナリまたはアプリ。
  7. ユーザー ID - プロセスの UNIX ID または PID - ターミナルに表示されるプロセス ID と同じです。

次に、日付/時刻、OSバージョン、レポートバージョン、そしてこのレポート固有のUUIDがあります。また、固有のスリープ/ウェイクIDもあります。

レポートには、システム整合性保護が有効になっているかどうかも表示されます。

次に、レポートにはクラッシュ自体の詳細が記載されます。この情報は非常に技術的な内容になる場合があり、通常はプログラマーやAppleがアプリケーションコードのどこで問題が発生したかを追跡し、修正できるようにすることを目的としています。

通常、クラッシュしたスレッド番号(この場合は最初のスレッド、スレッド0)が表示されます。スレッドとは、他のコードとは独立して実行されるコードのパスと考えてください。マルチコアCPUシステムでは、各コアで1つ以上のスレッドを実行でき、必要に応じてすべてのコアが並列に実行されます。これは並列コンピューティングと呼ばれます。

次に、クラッシュまたは例外の種類がリストされます。

例外タイプ: EXC_CRASH (SIGABRT)

この場合、SIGABRT(スレッドを中止、つまり強制終了するためのUNIXシグナル)が送信されました。シグナルとは、UNIXが実行中のプロセスに低レベルで送信するメッセージで、何らかの処理(この場合は終了)を指示します。

UNIX シグナルとその動作に関する詳しい情報はオンラインで入手できます。

次は例外コードですが、存在する場合はゼロになることが多いです。

各コードの前の「0x」は、そのコード値が10進数ではなく16進数、つまり「hex」であることを意味します。16進数は16進数であり、10進数のように10個の値を持つのに対し、16進数は16個です。16進数では、0から9までの数字に加え、AからFまでの数字が追加で使用されます。

16 進数システムがどのように機能するかについては、C プログラミング言語に関する優れた本を読めばわかります。

次は終了理由です。これは通常、クラッシュの原因を英語風に説明したものです。この場合は「Namespace DYLD, Code 1 Library missing」です。

DYLDはダイナミックローダー(Dynamic Loader)の略で、実行が必要なときにディスクからメモリにコードを動的にロードするOSの一部です。ターミナルでDYLDと入力してman dyldReturnキーを押すと、DYLDの詳細を確認できます。

名前空間とは、一部のプログラミング言語において、コードの一部を他のコードから分離するために用いられる命名規則です。「コード1 ライブラリが見つかりません」は、DYLDが動的リンクライブラリを読み込もうとしたが、読み込めなかったことを意味します。

プログラミングにおいて、ライブラリとはコードの束のことです。ライブラリは静的(ビルド時にアプリにリンクされる)または動的(実行時にアプリに読み込まれる)のいずれかです。

エラーが DYLD ロード エラーの場合、次の行に、エラーがどのライブラリであるか、およびディスク上のどこに存在するかが示されます。

「ライブラリがロードされていません: @rpath/VBoxRT.dylib」

この場合、VBoxRT.dylib は Oracle の Virtual Box アプリケーション用の動的ライブラリ (.dylib) です。DYLD は VBoxRT.dylib 動的ライブラリを検索しましたが、見つからなかったため、アプリケーションは実行できず、終了を指示する SIGABRT シグナルが送信されました。

macOSとiOSのアプリは実際には複数のコンポーネント(通常はバンドルと呼ばれるフォルダ)で構成されています。

この例では、アプリ バンドルの Contents フォルダー内の MacOS フォルダー内にアプリ バイナリが表示されます。

Librariesフォルダには、Apple SiliconとIntel x86の両方のライブラリが、Macプラットフォームアーキテクチャに対応した.dylib形式のフォルダに格納されています。これらは、DYLDによって必要に応じて実行時に読み込まれます。

アプリバンドルは非常にシンプルなものもあれば、非常に複雑なものもあります。コードやその他のリソースは、アプリバンドルの外に保存できます。

上記の例では、.dylib は外部に保存され、通常は実行時に必要に応じて読み込まれます。.dylib は通常、バンドルではなく単一のバイナリです。

iOSとmacOSでは、コードやその他のリソースをまとめたバンドルであるフレームワークもサポートされています。Finderでは、前述のポップアップメニューを使ってアプリバンドル内を確認するのと同じように、フレームワーク内を確認できます。フレームワークのバンドル内には常にバージョン番号が付与されます。

フレームワークは、アプリバンドル内、/Library/Frameworks、/user/~/Library/Frameworks に保存できます。macOS と iOS 自体の多くは、動的にロード可能なフレームワークとして実装されています。

Appleは、macOSおよびiOSコードの読み込みとバインディングのプロセスを詳細に説明した開発者向けフレームワークプログラミングガイドを提供しています。静的に関連する2つのコードを結合することは、バインディングではなくリンクと呼ばれ、アプリケーションをコンパイラでビルドする際に行われます。

静的コードはすべて一度にロードされるため、システムメモリの消費量が増える可能性があります。

Apple には、Objective-C および Swift ランタイムの詳細を説明した別の開発者ドキュメントもあり、どちらにもアプリ実行中にコードがどのようにロードされるかについての追加情報が含まれています。

動的コードローディングは、SmallTalkなどの言語で1970年代後半にまで遡ります。Appleのプラットフォームでは、1997年にAppleがNeXTを買収したことで実現しました。同時に、動的リンクとイントロスペクションの先駆者となったNeXTのプログラミング言語Objective-Cも買収しました。

NeXTStep Developer - 動的バインディングを使用する最初の開発者パッケージの 1 つ。

NeXTStep Developer - 動的バインディングを使用する最初の開発者パッケージの 1 つ。

現在でも、Apple のソフトウェアは Objective-C か、同じく動的なリンクと読み込みを使用する Apple 独自の Swift で書かれています。

動的読み込みでは、アプリのコードとリソースのすべてを一度にメモリに読み込む必要がないため、アプリのメモリ使用量を削減できます。動的読み込みの欠点は、アプリの実行中にディスクからリソースを読み込む必要があるため、処理速度が遅くなる場合があることです。

これは、macOS で悪名高い回転するビーチボール カーソルが発生する一般的な原因の 1 つです。

クラッシュレポートの次の部分では、「参照元:」の下に、問題のあるコードを呼び出した呼び出し元プロセスまたはコードバイナリが示されます。この場合、アプリのバンドル内に保存されているメインのVirtualBoxアプリケーションバイナリでした。

英語で読める情報の最後の部分は「Reason:」で、クラッシュが発生した理由を人間が読める形式で提供しようとします。

「'/usr/lib/VBoxRT.dylib'(そのようなファイルは存在しません、dyldキャッシュにもありません)、(セキュリティポリシーにより@パスの展開は許可されていません)

(起動時に終了しました。バックトレースは無視してください)」。

これは、必要なライブラリがディスク上の /usr/lib/VBoxRT.dylib にあるはずだったが、そこに存在しなかった (通常はインストール時に VirtualBox インストーラによってそこに配置されます)、DYLD が以前にそれをロードしていなかった、そしてアプリが起動時に強制終了したことを意味します。

まとめると、上記の例では、VirtualBox は起動されましたが、必要な動的ライブラリが見つからなかったため、macOS によって強制終了されました。すべての情報が収集され、クラッシュレポートに追加されました。

追加のコンソール情報とスタックトレース

クラッシュ レポートの残りの情報はより技術的なため、ここでは詳細には触れませんが、何が起こったのかをすぐに判断できる内容がいくつかあります。

特に、各スレッド番号の下にリストされているアプリのコード実行を逆順に追跡することで、クラッシュの原因の手がかりを探すことができます。すべてのクラッシュがライブラリの不足に関連しているわけではないため、アプリは正常に起動したにもかかわらず、単にコードにプログラミングエラーがあり、それがクラッシュの原因となっている可能性もあります。

プログラマーは、存在しないシステムコードを呼び出したり、関数のパラメータを変更したりするといったミスを犯すことがあります。また、メモリアクセスエラーや、コード内の変数を過剰なデータで上書きし、メモリ内の隣接する重要なデータを上書きしてしまうといったミスも考えられます。

これらのエラーはすべてクラッシュを引き起こす可能性があります。

この情報は通常、「理由:」セクションの直後にリストされ、番号付きの関数呼び出しのリスト、関数名、メモリ上のアドレス、そしてロード方法が記載されています。このセクションでは、関数のリスト(スタックトレースと呼ばれます)を逆順、つまり下から上へ読むことに注意してください。

これは関数が実際に実行される順序です。

この場合、スタックは非常に短く、起動時に必要なライブラリをロードできなかったため、主にDYLDの準備と停止/中止シグナルで構成されています。しかし、エラーによってはスタックが非常に複雑になる場合があります。

通常、スタックの最上部 (最後) にある最後の関数が問題の原因となりますが、常にそうであるとは限りません。

これを知っておくと、クラッシュの診断に役立ちます。スタックから、失敗した関数呼び出しを正確に特定できるからです。その後、Appleの開発者向けドキュメントでその関数名を調べることで、何が起こったのかについてのさらなる手がかりを得ることができます。

クラッシュした関数を含むフレームワークまたはライブラリの名前がスタック トレースにリストされる場合があり、これによりさらに多くの情報が提供されます。

クラッシュレポートのスタックブロックの後には、スレッドの状態に関する情報がいくつか表示されますが、これは開発者以外にはあまり関係ありません。その後に、スレッドが実行されていたCPU、エラーコード(ある場合)、そしてトラップ番号が表示されます。トラップとは、何らかのイベントが発生したときに呼び出されるOSコードへの挿入ポイントです。

クラッシュメモリと概要

次に、クラッシュに関係するバイナリ (コンパイルされたコード) に関する情報がいくつかあります。これらの情報は、クラッシュ レポートの上部近くにリストされている情報と通常は同じですが、常に同じであるとは限りません。

その後に、外部変更サマリー(External Modification Summary)があります。これは、このプロセスとやりとりしたプロセスIDのサマリーと、コードのどの部分がメモリ上にあり、どの部分がまだディスク上に残っているかを示す仮想メモリ(VM)情報です。仮想メモリとは、システムで使用可能なメモリの総量を増やすために、OSが実際のRAMのように使用するディスク領域のことです。

さらに、「リージョンタイプ」情報があり、スタック、VM、リンクセグメントとテキストセグメント、DYLDと共有メモリに関する追加情報がまとめられています。開発者でない限り、この情報は無視して構いません。

各クラッシュレポートの最後には「フルレポート」セクションがあり、これは基本的に.ipsファイル全体の生のJSONダンプをテキスト形式で提供します。生のJSONには、コンソールウィンドウには表示されない追加情報(Apple MacのモデルID、CPUの種類、コード署名など)が含まれています。

また、アプリでは複数のスレッドが実行される場合があり、上記のような概要が各スレッドごとに表示されます。ただし、通常はクラッシュしたスレッド番号がレポートの一番上に表示されるため、どのスレッド番号を確認すればよいかがわかります。

初心者にとっては、これらすべてが手に負えないように思えるかもしれませんが、クラッシュレポートの読み方に慣れれば、何が起こったのか、そしてどう対処すればいいのかを素早く簡単に把握できるようになります。上記の例では、必要なライブラリが不足していたため、インストーラーを使ってアプリを再インストールするだけで済みます。

Apple はオンラインで詳細なコンソール ユーザー ガイドを提供しており、非常に有益で役立ちます。