20

私は何年にもわたって多くのゲーム プロジェクトでミニダンプを使用してきましたが、有効なコール スタックを持つ可能性は約 50% のようです。コールスタックを改善するにはどうすればよいですか?

最新の dbghelp.dll を exe ディレクトリに入れてみました。それはいくつかを助けるようです。

Visual Studio 2008 または 2010 はどちらが優れていますか? (私はまだ VS 2005 を使用しています)。

私が使用するコードは、このサンプルのようになります。

4

5 に答える 5

30

ダンプで見つかったコール スタックの精度を向上させるためにできることの 1 つは、Visual Studio 以外のデバッガーを使用することです。具体的には、WinDbg または dbgeng.dll にある "Windows デバッガー" デバッグ エンジンを使用する別のツールを使用します ( Visual Studio が使用する "Visual Studio Debugger" デバッグ エンジンに)。

私たちの経験では、WinDbg は、Visual Studio が使用できない、または非常に不正確なコール スタックを生成するのと同じダンプから適切なコール スタックを生成する点で 100% 信頼性があります。私が知る限り、未処理の例外がクラッシュの原因である場合、WinDbgは例外 callstack を再構築/回復するトリッキーなプロセスを自動的に実行しますが、Visual Studio は実行しません (または実行できませんか?)。2 つのデバッガーは、スタックの解釈に異なるヒューリスティックを使用します。

WinDbg は最初は気が遠くなる可能性があるため、WinDbg を簡単にする方法、または直接使用する必要を回避する方法についてのクイック ガイドを次に示します。

良いコールスタックを抽出するための単なる人間のガイド

これらは、「最も速い/最も簡単」から「最も遅い/最も解釈が難しい」の順に並べられています。

  1. 最も簡単なオプション: Microsoft の DbgDiag を使用する

これは、一般的な問題の多くの分析を自動化するあまり知られていないツールであり、プログラマー以外や顧客に提供するのに十分簡単です。これは高速で、ほぼ確実であり、受信したクラッシュ ダンプをすばやく分析するための「頼りになる」ツールになっています。

  • 「DebugDiag 分析」アプリケーションを起動します。
  • メインページで「CrashHangAnalysis」チェックボックスを選択します
  • ダンプをメイン ページの [データ ファイル] ペインにドラッグ アンド ドロップします。
  • 「分析開始」をクリック


数秒から数分後、問題の分析、関連するすべてのスレッドに関する情報、完全なコール スタックなどを含む素敵な .mhtml ファイルが出力されます。すべてハイパーリンクされており、使いやすいです。

DebugDiag は、可能ではあるが WinDbg では困難な、より複雑な分析の一部を自動化します (アプリケーション内の 350 のスレッドのどれがデッドロックの原因であるかを追跡するなど)。

注: セキュリティ上の理由から、Chrome では .mhtml ファイルをダウンロードしたり開いたりすることはできません。そのため、使用するには Internet Explorer または Microsoft Edge で開く必要があります。これは煩わしいので、DebugDiag チーム (dbgdiag@microsoft.com) に形式をプレーンな HTML に変更するよう要求しました。

  1. 中間のオプション: Visual Studio の代替デバッグ エンジンとして WinDbg をインストールします。
  • まだインストールされていない場合は、Visual Studio をインストールします。これは、次のステップの前に行う必要があります。
  • Windows ドライバー キット (WDK)をインストールする
  • Visual Studio を起動し、(この部分が重要です! ) 新しい [ファイル -> 開く -> クラッシュ ダンプ...] オプションを使用してダンプを開きます。これにより、Windows デバッガーを使用してクラッシュ ダンプがデバッグされます (代わりに、Visual Studio でダンプをドラッグ アンド ドロップするか、標準の [ファイル -> 開く -> ファイル...] オプションを使用してダンプを開くと、デバッグされます)。古い Visual Studio デバッグ エンジンを使用しているため、適切なオプションを使用するように注意してください)。
  • これで、正しいコール スタックを確認し、Visual Studio GUI を使用してナビゲートできるようになりましたが、動作が異なる場合があります (ウォッチ ウィンドウではなじみのない WinDbg 構文を使用する必要がある、スレッド ID が異なるなど)。注: Visual Studio の UI は、特に多くのスレッドが関係し、「スレッド」または「並列スタック」ウィンドウが開いている場合、非常に遅くなることがあります。
  1. ハードコア オプション: WinDbg を直接使用する
  • WinDbg.exe を起動します
  • ダンプを WinDbg ウィンドウにドラッグ アンド ドロップします。
  • 入力してEnter!analyze -vキーを押します。しばらくすると、WinDbg はクラッシュ コール スタックを吐き出し、問題の原因を推定します。デッドロックを分析している場合は、試すことができます!analyze -v -hang。WinDbg は、関連する依存関係チェーンを表示することがよくあります。


この時点で、必要な情報がすべて揃っている可能性があります。ただし、Visual Studio デバッガーでプロセスの状態を調べたい場合は、次の追加の手順を実行できます。

  • Visual Studio でクラッシュ ダンプを開く
  • コールスタック ウィンドウを右クリックし、[逆アセンブルに移動] を選択します。
  • WinDbg の出力コールスタックの一番上の行から 16 進アドレスを [逆アセンブリ] ウィンドウの [アドレス] バーに貼り付けて、Enter キーを押します。逆アセンブルされたコードを見ると、クラッシュの場所にいます。
  • 逆アセンブリ ウィンドウを右クリックし、[ソース コードに移動] を選択して、その場所のソース コードに移動します。これで、クラッシュ サイトのソース コードが表示されます。

注: 上記のすべてでは、正しいシンボル サーバー パスを構成する必要があります。そうしないと、コール スタックでシンボルを解決できません。_NT_SYMBOL_PATH 環境変数を設定して、Visual Studio、WinDbg、および DebugDiag で自動的に使用できるようにすることをお勧めします。

于 2015-10-28T14:50:17.437 に答える
6

コールスタックに何が欠けていますか? 有効な関数名 (つまり、CFoo:Bar() ではなく 0x8732ae00) に解決されないアドレスがたくさんありますか? その場合、必要なのは、.PDB をデバッガーが見つけられる場所に配置するか、シンボル サーバーをセットアップして、モジュール ペインの右クリック コンテキスト メニューで [シンボル パス] を設定することです。

誰かが新しい Perforce チェンジリストをチェックインするたびに、すべてのバイナリからすべての .PDB を保存します。これにより、オフィス内の誰かまたは小売店の顧客からダンプが返されたときに、彼らがいたゲームのバージョンに対応する .PDB が得られます。ランニング。シンボル サーバーとパスを設定したら、.mdmp をダブルクリックするだけで、いつでも機能します。

または、関数が 1 つしかないように見えるコール スタックがありますか? 0x8538cf00 のように、スタック内でそれより上には何もありませんか? もしそうなら、あなたのクラッシュは実際にはスタック自体が壊れています。バックチェーンのリターン アドレスが上書きされた場合、当然、デバッガーはそれらを解決できなくなります。

また、ミニダンプを実際に発行するスレッドが、クラッシュの原因となった例外をスローしたスレッドではない場合もあります。[スレッド] ウィンドウを調べて、他のスレッドの 1 つに問題のあるコードが含まれているかどうかを確認します。

「リリース」ビルド (つまり、すべての最適化フラグをオンにしてコンパイルしたビルド) をデバッグしている場合は、デバッガーがローカル変数やその他のデータを見つけるのに苦労するという事実に対処する必要があります。これは、最適化をオンにするということは、コンパイラがデータをレジスタに保持し、計算を折りたたむことを可能にし、一般的に、データが実際にスタックに書き込まれないようにするさまざまなことを行うことを意味するためです。これが問題である場合は、逆アセンブリ ウィンドウを開いて手動でデータを追跡するか、デバッグ バイナリを再構築して問題を再現し、問題を確認する必要があります。

于 2009-10-12T05:01:21.437 に答える
4

スタック ダンプが必要な場合は、フレーム ポインターの最適化をオフにします。フレーム ポインタは、スタックフレームを明示的に定義するために使用されます。それらがないと、デバッガーは各フレームの位置を推測する必要があります。

于 2009-10-12T08:48:48.157 に答える
0

私はミニダンプを使用せず、スタックを「手動」でログファイルにダンプします ( www.ddj.com/cpp/185300443および Windows x64 でスタック フレームをログに記録する方法 を参照)。

あなたと同じような動作に遭遇します。有効な呼び出しスタックがある場合とない場合があります。まれに、スタックが実際に破損している可能性があります。すべてのケースの 1/3 では、インストールされた Exception ハンドラがまったく呼び出されません! Windowsの構造化された例外処理の問題だと思います。

于 2009-10-12T08:41:50.213 に答える