2011-12-09 5 views
5

できるだけ早くコールスタックをキャプチャしようとしています。コールスタックをすばやくキャプチャします。

void* addrs[10] = {}; 
DWORD hash; 
RtlCaptureStackBackTrace(0, 10, addrs, &hash); 

for(size_t i = 0; i <10; ++i) 
{ 
    std::cout << addrs[i] << '\n'; 
} 

これは、メモリトラッキングシステムに使用するためのものであるので、それは彼らが後で(一部のユーザーに応じたイベントを駆動することができれば、私はアドレスの配列で終わることを完全に罰金です。今のところ、これは私が持っているものです)人間が読めるようなものに変えてください。

  • 私は addrsを人間が読み取り可能なものにするにはどうすればよいですか? (下記を参照)
  • RtlCaptureStackBackTraceより速いものはありますか?
  • コールスタックをキャプチャするためのクロスプラットフォームの方法はありますか?

編集:

私はSymFromAddrSymGetLineFromAddr64を使用することによって、人間読み取り可能な情報にアドレスを回しました。しかし、私のバージョンnewは、CaptureStackBackTraceを使用すると、オリジナルよりも約30倍長くなり、そのほとんどはスタックトレースのためです。私はまだ高速なソリューションを探しています!

答えて

2

コールスタックをキャプチャするクロスプラットフォームの方法はありますか。

速い答えは、残念ながらそれはできません。異なるコンパイラとプラットフォームは、スタックを別々に編成します。コンパイラからの "助け"がなければ、スタックを正確にトレースすることはできません。スタックを使用しているプラ​​ットフォームでは、 EBPまたはRBPのいずれかの値を使用してスタックを上に移動することになり、32ビットx86実行可能ファイルまたはx86_64実行可能ファイルを実行しているかどうかによっても異なります。さらに、UNIXアプリケーションのバイナリインターフェイス(ABI)とWindows ABIを管理するルールはまったく異なります。

  1. Unixの32ビットABI
  2. 64ビットABI
  3. のUnix
  4. Windows 32ビットABI
  5. :だから一般的に、あなたは、少なくとも4つの異なる可能性をサポートするために持って終了するつもりですWindows 64ビットABI

UNIX 64ビットABIでは、スタックフレームのベースポインタをサポートするかどうかをコンパイラが選択できるようになっているので、ポインタは保証されません。コンパイラは、別個のベースポインタを使用することなく、スタックポインタ自体に対してすべてのスタック変数を参照することを単に選択することができる。それでもUNIX 64ビットABIに準拠していると考えられます。

これらのすべてのバリエーションを見ると、信頼性の高いクロスプラットフォームのスタックトレーサを作成するのに非常に苦労するでしょう。ターゲットとしているプラ​​ットフォームで利用できるツールを使用することをお勧めします。複数のプラットフォームをサポートする必要がある場合は、スタックトレースを確実に実行するために、プラットフォーム固有のツールを使用する際に、ある程度のコードの重複が発生します。

0

クロスプラットフォームの方法はありませんが、このトリックを行うクロスプラットフォームのライブラリがあります。 It's a common requirement for garbage collectors

残念ながら、私はこれらのライブラリを推薦するには十分ではありません。 MMgcには何かが埋め込まれています(上記のリンクに説明があります)。私はHans Boehmのガベージコレクターが別のものを持っていると確信しています。

これらのライブラリは、一般にプラットフォーム固有の呼び出し(WindowsのRtlCaptureStackBacktraceなど)に依存します。そのようなライブラリがプラットフォーム固有の呼び出しより速くなった場合、私は驚くだろう。そのようなライブラリが大幅に遅くなった場合、私はまた驚くでしょう。唯一の質問は、Windows API呼び出しを直接呼び出すか、その呼び出しを別のライブラリ経由でルーティングするかどうかです。