web-dev-qa-db-ja.com

Windows / C ++:「Exception Offset」を持つ例外がスローされたコード行を見つけることは可能ですか?

ユーザーの1人が製品のスタートアップで例外を持っています。彼女はWindowsから次のエラーメッセージを送信しました。

  Problem Event Name:                        APPCRASH
  Application Name:                          program.exe
  Application Version:                       1.0.0.1
  Application Timestamp:                     4ba62004
  Fault Module Name:                         agcutils.dll
  Fault Module Version:                      1.0.0.1
  Fault Module Timestamp:                    48dbd973
  Exception Code:                            c0000005
  Exception Offset:                          000038d7
  OS Version:                                6.0.6002.2.2.0.768.2
  Locale ID:                                 1033
  Additional Information 1:                  381d
  Additional Information 2:                  fdf78cd6110fd6ff90e9fff3d6ab377d
  Additional Information 3:                  b2df
  Additional Information 4:                  a3da65b92a4f9b2faa205d199b0aa9ef

この情報を持つ例外が発生したソースコード内の正確な場所を見つけることは可能ですか?

ユーザーコンピューターで発生したエラーの場所を特定するための、Windows上のC++プログラマーの一般的な手法は何ですか?

プロジェクトはリリース構成でコンパイルされ、PDBファイルが生成されます。

私の質問が素朴すぎないことを願っています。

43
Pavel

はい、可能です。ユーザーが実行したのとまったく同じバイナリでデバッグを開始し、DLLがロードされ、それに対応するPDBファイルがあることを確認します。=のデバッグ+ Windows +モジュールを確認してください。 DLLベースアドレス。オフセットを追加します。デバッグ+ウィンドウ+逆アセンブリを行い、アドレスフィールドに計算したアドレスを入力します(プレフィックス0x)。これにより、例外の原因となった正確なマシンコード命令が表示されます。 -+ [ソースコードに移動]をクリックして、一致するソースコード行を表示します。

これはステートメントを示していますが、これは通常、原因を診断するには十分ではありません。 0xc0000005例外はアクセス違反であり、多くの原因が考えられます。多くの場合、コードを取得することさえできません。プログラムは、スタックが破損しているために忘却に陥った可能性があります。または、実際の問題は遠く離れた場所にあり、ポインターを操作してヒープを破壊しました。また、通常は、爆撃したステートメントでプログラムがどのように終わったかを示すスタックトレースが本当に必要です。

必要なのはミニダンプです。ユーザーがVistaまたはWin7を実行している場合、ユーザーから簡単に取得できます。 TaskMgr.exeの[プロセス]タブを起動し、クラッシュダイアログを表示している間に爆撃されたプログラムを選択します。それを右クリックして、ダンプファイルを作成します。

これをスムーズにするために、この手順を本当に自動化する必要があります。 this thread の私の答えにヒントがあります。

67
Hans Passant

ミニダンプがある場合は、Visual Studioでそれを開き、元のバイナリとPDBを含む適切なフォルダーにMODPATHを設定し、「実行」するように指示します。また、Microsoftシンボルサーバーからシンボルをロードするように指示する必要があります。エラーの場所にコールスタックが表示されます。特定のスタックの場所のソースコードを確認しようとすると、ソースの場所を尋ねられる場合があります。その場合は、適切なソースフォルダーを選択します。 MODPATHは、ミニダンプファイルの名前を持つ「プロジェクト」のデバッグコマンドラインプロパティで設定されます。

4
Permaquid

私はこのスレッドが非常に古いことを知っていますが、これはGoogleのトップレスポンスであったため、$。02を追加したかったのです。

ミニダンプが最も役立ちますが、シンボルを有効にしてコードをコンパイルしている限り(.pdbを使用せずにファイルを送信し、.pdbを保持してください!)、これがMSVCデバッガーを使用していた行を調べることができます。 Windowsデバッガー。それに関するMSNの記事:

http://blogs.msdn.com/b/danielvl/archive/2010/03/03/getting-the-line-number-for-a-faulting-application-error.aspx

2
std''OrgnlDave

ランタイムベースのメタデータ対応言語(.NETやJavaなど)とは異なり、ソースコード情報はコンパイル済みのC++コードでは保持されません。 PDBファイルは、デバッガがコンパイルされたコードをソースに逆方向にマップするのに役立つシンボルインデックスですが、クラッシュダンプからではなく、プログラムの実行中に実行する必要があります。 PDBを使用する場合でも、リリースでコンパイルされたコードは、デバッガーがソースコードを識別できないようにすることができる多くの最適化の対象となります。

エンドユーザーマシン上でのみ現れる問題のデバッグは、通常、注意深い状態のログと、ソースに関する詳細な指向の時間と労力の問題です。ユーザーとの関係に応じて(たとえば、社内のIT開発者である場合)、ユーザーのマシンの仮想マシンイメージを作成し、デバッグに使用できる場合があります。これにより、ユーザーのワークステーションにインストールされたソフトウェアと標準実行プロセスを複製します。

1
Dan Story