私が個人的に使用するために作成した小さなユーティリティ(C++で記述)が昨日ランダムにクラッシュし(これまで問題なく約100時間以上使用しました)、通常はこれを実行していませんが、少し感じていました冒険的で、問題についてもっと学びたいと思っていました。イベントビューアにアクセスして、クラッシュについてWindowsが記録した内容を確認することにしました。
Faulting application StraightToM.exe, version 0.0.0.0, time stamp 0x4a873d19
Faulting module name : StraightToM.exe, version 0.0.0.0, time stamp 0x4a873d19
Exception code : 0xc0000005
Fault offset : 0x0002d160,
Faulting process id: 0x17b4
Faulting application start time: time 0x01ca238d9e6b48b9.
私の質問は、これらのそれぞれが何を意味するのか、そしてこれらをどのように使用してプログラムをデバッグするのかということです。私がこれまでに知っていることは次のとおりです。例外コードはエラーを説明し、0xc0000005はメモリアクセス違反です(所有していないメモリにアクセスしようとしました)。私は特に次のことについてもっと知りたいと思っています。
私は主にC++プログラマーなので、Assemblyについては知っていますが、知識は非常に限られていることに注意してください。さらに、これは実際には修正が必要な深刻な問題ではありません(また、プログラムの性質上、簡単に再現することもできません)。これらのエラーメッセージの意味を理解するための言い訳としてこれを使用しています。私がオンラインで見つけたこれらのクラッシュログに関する情報のほとんどは、通常、エンドユーザーを対象としているため、(プログラマーとしての)私にはあまり役に立ちませんでした。
前もって感謝します
64ビットのタイムスタンプは、アプリケーションのプライマリスレッドが1601年1月1日(UTC)から100ナノ秒間隔で作成された時間です(これはFILETIME
として知られています)。 32ビットのタイムスタンプは確かにtime_t
format(モジュールが作成され、モジュールのヘッダーに保存された時刻を示します)。
0x0002d160はモジュールのロードアドレスからのオフセットだと思います(絶対アドレスには低すぎるようです)。 Visual Studioを起動し、デバッガーを起動して、「モジュール」デバッグウィンドウを確認します。あなたのexeファイルはそこにリストされているはずです。モジュールがロードされているアドレスを見つけ、そのアドレスに0x0002d160を追加して、結果のアドレスで逆アセンブリを確認します。 Visual Studioは、アセンブリと混合されたソースコードを表示します。問題の原因となったソース行を、問題なく把握できるはずです。
この情報を使用して事後分析を行うことができることはあまりありません。
有用な情報は、例外コード0xc0000005です。この場合、これは単にアクセス違反を意味します。したがって、nullまたは所有していない他のメモリビットを逆参照しました。
障害オフセットは、DLLがメモリにロードされた場所からのオフセットであるため、理論的にはベースアドレスに追加して、問題のあるコードを見つけることができますが、よくわかりません。 。
これをデバッグするための最善の策は、次にこれが発生したときにデバッガーでキャッチすることです。 画像ファイル実行オプション を使用して、 デバッガー でアプリを自動的に実行できます。シンボルの準備ができていることを確認してください(現在RELEASEを使用している場合は、DEBUGの構築を検討してください)。
デバッグの神ジョン・ロビンズは、次のような状況を支援するためにCrashFinderと呼ばれる小さなツールを作成しました: https://www.wintellect.com/crashfinder-2-8-yes-native-code-still-lives/
公開するビルドごとにPDBを保存することをお勧めします(これはプライベートでのみ使用するツールのように聞こえますが、最新のビルドのためにPDBシンボルを保持しておくことをお勧めします)。
ここにはまだ良い答えがないようです。開発環境の外でクラッシュが発生した場合はどうなりますか。オフセットは、アセンブリコードがクラッシュするアドレスだと思います。ただし、そのdllのアセンブリコードの開始位置を知る必要があります。または、アセンブリツールを使用してdllを開き、開始アドレスにオフセットを追加してアセンブリコードを見つけることができるため、開始アドレスを知る必要がない場合もあります。