1

C++/CX で記述された Windows ストア アプリケーション (Windows 8 用) があり、コードのチャンクを try/catch ブロックにラップしました。

catch ブロックは機能しており、例外をキャッチしていますが、これまでのところ、完全な例外スタックではなく、例外の「メッセージ」部分のみを出力できるようです。

try
{
...
}
catch(Exception^ e)
{
   LogMessage("Exception caught: " + e->ToString());
}

例外がキャッチされると、LogMessage は次のテキストのみを出力します。

"Exception caught: The object already exists"

e->ToString() と e->Message を試しましたが、どちらも同じ出力になり、完全な例外スタックは含まれません。

C# では完全な例外スタックを出力するのは本当に簡単なようですが、なぜ C++/CX では難しいように見えるのでしょうか?

4

2 に答える 2

2

これは C++/CX では困難です。これは、スタックに含まれる関数を特定するには、コードでデバッグ シンボルを解析する必要があるためです。C# では、CLR は実行時にどのメソッドがスタック内にあるかを記憶するために機能しますが、C++/CX では、関数の名前は結果のバイナリに記録されません。別の言い方をすれば、C# で得られるスタック トレースは、C# の機能であるリフレクションに依存しています。

さらに、例外は、C++/CX API ではなく、プレーンな COM API であるコードへの呼び出しによって発生する場合があります。HRESULTこのような場合、例外は、例外がスローされた時点ではなく、その下にあるエラー リターン コードから生成されます。(実際、これはコンポーネントの境界を超えるたびに発生することです。操作の両側が C++/CX であっても、これはプレーンな COM で処理されます) そのため、トレースに必要なスタックは使用できなくなります。

C++ 例外はスタック トレースを記録しません。プラス面としては、未処理の例外が発生したときにネイティブ プログラムからミニダンプを収集できるため、必要に応じてデバッガーを使用してスタックを表示できます。

于 2013-03-22T02:10:37.677 に答える
1

C++/CX プログラムは純粋なアンマネージ C++ コードであることに注意してください。CX 言語拡張機能は、C++ コードで WinRT 型を簡単に使用できるようにするだけで、COM 実装の詳細を隠します。そのため、コード オプティマイザの完全な処理が行われます。これは、スタック ウォークが安全に実行できることを保証しようとはしません。例外をスローしないリーフ関数では特にそうです。スタック起動フレームのベースを示す重要な EBP レジスタの設定を簡単に省略できます。

これは、C# などのマネージ コードには当てはまりません。スタック ウォークは、ガベージ コレクトされたランタイム環境では非常に重要です。ガベージ コレクターは、ガベージを収集するときにオブジェクト参照を見つけるためにそれらを実行する必要があります。コード アクセス セキュリティもスタック ウォークに依存します。幸いなことに、例外のスタック トレースの生成も非常に簡単になりました。フレームワーク API でも公開されており、StackTrace クラスを使用すると、独自のコードでスタックを調べることができます。

これを簡単に修正することはできません。問題を解決するにはデバッグ シンボルが必要です。そして、DbgHelp API からの StackWalk64。プログラムが Windows 関数の腸のどこかでクラッシュしたため、まだどこにも到達しない可能性があります。C++ では速度が利便性より優先されます。

于 2013-03-22T03:05:16.353 に答える