デバッグ モードで C++ プログラムがクラッシュすることがあり、内部メモリ管理ルーチンの一部 (未割り当てメモリへのアクセスなど) でアサーションが失敗したことを示すメッセージ ボックスが表示されます。しかし、スタック トレースが得られなかったので、どこから呼び出されたのかわかりません。スタック トレースを取得するにはどうすればよいですか、または少なくとも (ライブラリ/組み込みルーチンではなく) コード内で失敗した場所を確認するにはどうすればよいですか?
7 に答える
クラッシュが発生した場合は、デバッグ ビルドかリリース ビルドかに関係なく、クラッシュが発生した場所に関する情報を取得できます。また、ソース コードがないコンピューターを使用している場合でも、呼び出し履歴を確認できます。
これを行うには、EXE でビルドされた PDB ファイルを使用する必要があります。クラッシュした EXE と同じディレクトリ内に PDB ファイルを配置します。注: ソース コードが同じであっても、最初の EXE と 2 番目の PDB を使用して 2 回ビルドしても機能しません。EXE で構築された正確な PDB を使用する必要があります。
次に、クラッシュしたプロセスにデバッガーをアタッチします。例: windbg または VS。
次に、スレッド ウィンドウを開いたまま、コール スタックをチェックアウトします。クラッシュしたスレッドを選択し、そのスレッドのコールスタックを確認する必要があります。各スレッドには異なるコール スタックがあります。
VS デバッガーが既に接続されている場合は、クラッシュの原因となっているソース コードに自動的に移動します。
PDB を持っていない、使用しているライブラリ内でクラッシュが発生している場合。あなたにできることは何もありません。
VS を搭載したマシンでデバッグ バージョンを実行すると、VS を起動してスタック トレースを表示できるはずです。
問題は、本当の問題がコール スタックにないことです。ポインターを 2 回解放すると、プログラムとは関係のない別の場所でこの問題が発生する可能性があります (次に何かがヒープ データ構造にアクセスするとき)。
このブログでは、何が起こっているのかを理解できるように、コール スタックに問題を表示するためのヒントをいくつか書いています。
最良のヒントは、gflags ユーティリティを使用して、ポインターの問題がすぐに問題を引き起こすようにすることです。
キャッチされていない例外のハンドラーを設定することで、ミニダンプをトリガーできます。ミニダンプのすべてを説明する記事は次のとおりです
Google は実際にBreakPadと呼ばれる独自のオープン ソース クラッシュ ハンドラーを実装しました。これは、mozilla も使用していると思います (それは、より深刻なものが必要な場合です。つまり、リッチで堅牢なクラッシュ ハンドラーです)。
クライアント システムに事後分析デバッガーをインストールすることもできます。これは、アプリケーションにダンプ作成機能が組み込まれていない場合に情報を取得する適切で一般的な方法です (おそらく、まだ情報を取得する必要がある古いバージョンの場合)。
Windows 上のワトソン博士は、次のコマンドを実行してインストールできます。drwtsn32 -i
実行drwtsn32
すると (オプションなしで)、構成ダイアログが表示されます。これにより、後で WinDbg などで分析できるクラッシュ ダンプ ファイルを作成できます。
CrashFinderは、DLL と報告された例外のアドレスを指定して、例外の場所を特定するのに役立ちます。
このコードをアプリケーションに統合して、キャッチされていない例外がある場合にスタック トラップを自動的に生成することができます。これは通常、ハンドルされていないすべての例外へのコールバックを指定できるようにするSetUnhandledExceptionFilter__try{} __except{}
の呼び出しを使用するか、呼び出しで実行されます。
私の記憶が正しければ、メッセージ ボックスには「再試行」というボタンが必要です。これにより、アサーションが発生した時点でプログラムが (デバッガーで) 中断されます。
これにはポピーを使用できます。コード全体にいくつかのマクロを振りかけるだけで、実際のパラメーター値、ローカル変数、ループ カウンターなどと共にスタック トレースが収集されます。これは非常に軽量であるため、クラッシュからこの情報を収集するためにリリース ビルドに残すことができます。エンドユーザーのマシン上