2

Linux でメモリー用の内部プロファイラーを実装する予定です。malloc/free/realloc ごとにスタックを保存したい。「pstack」を使用して毎回スタック トレースを取得しようとしています。しかし、オーバーヘッドが高すぎます。Cコードでコールスタックを取得するための軽量なアプローチはありますか?

「valgrind、Google プロファイラー」などのツールがあることは知っていますが、各アクションのスタックをどのように記憶するかはわかりません。

どんなコメントでも大歓迎です。

ありがとう。

4

4 に答える 4

4

比較的高速な GNU 関数がbacktrace()あります。アドレスの配列を返すだけです。

これらのアドレスを関数名に解決するbacktrace_symbols()には、より重いものを使用する必要がありますが、あまり頻繁に実行する必要がないことを願っています。

実際に名前を解決するには、リンカー オプションbacktrace_symbols()を使用する必要があります。-rdynamic

詳細man backtraceについては、を参照してください。

于 2009-08-05T08:05:02.417 に答える
2

呼び出し元を取得する独自の関数を作成できます。

static inline void *get_caller(void) {
    unsigned long *ebp;

    /* WARNING: This is working only with frame pointers */
    asm ("movl %%ebp, %0" : "=r" (ebp) : );
    ebp = (unsigned long*)*ebp;
    ebp = (unsigned long*)*(ebp+1);
    return ebp;
}

void *malloc(void) {
    void *caller = get_caller();
    ...    
}

" ebp = (unsigned long*)*ebp;" は、スタックを通過させます (そのスタック トレースがさらに必要な場合)。

于 2009-08-05T12:00:24.173 に答える
0

今、64ビットで問題に遭遇しました。

64 ビットでは、RBP は厳密に維持されていません。たとえば、gcc -O3 は RBP を通常の呼び出し側保存レジスタとして使用します。したがって、この場合、フレーム ポインターからコール スタックを取得することはできません。:(

コメントはありますか?

于 2009-08-14T01:30:35.520 に答える
0

malloc 自体を呼び出す backtrace_symbols() による再帰に注意してください。

また、backtrace() とその仲間の最初の使用時に、動的リンカが libgcc をロードしようとすることにも注意してください。これにより、malloc が再び呼び出されます。

ギラッド

于 2009-08-09T12:09:39.290 に答える