6

Mac OS X の C++ アプリで現在のスタックを保存してから印刷する方法を考え出そうとしています。問題は実際にはコンパイル オプションであると思われますが、よくわかりません。

Darwin/Leopard のバックトレース コードを試してみましたが、dladdr が呼び出され、dladdr を呼び出す自分のコードと同じ問題が発生します。

元の投稿: 現在、次のコードでスタックをキャプチャしています:

int BackTrace(Addr *buffer, int max_frames)
{
    void **frame = (void **)__builtin_frame_address(0);
    void **bp = ( void **)(*frame);
    void *ip = frame[1];
    int i;

    for ( i = 0; bp && ip && i < max_frames; i++ )
    {
        *(buffer++) = ip;
        ip = bp[1];
        bp = (void**)(bp[0]);
    }

    return i;
}

これはうまくいくようです。次に、次のように dladdr を使用して、見ているスタックを印刷します。

Dl_info dli;
if (dladdr(Ip, &dli))
{
    ptrdiff_t       offset;
    int c = 0;

    if (dli.dli_fname && dli.dli_fbase)
    {
        offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_fbase;
        c = snprintf(buf, buflen, "%s+0x%x", dli.dli_fname, offset );
    }
    if (dli.dli_sname && dli.dli_saddr)
    {
        offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_saddr;
        c += snprintf(buf+c, buflen-c, "(%s+0x%x)", dli.dli_sname, offset );
    }

    if (c > 0)
        snprintf(buf+c, buflen-c, " [%p]", Ip);

これはほとんど機能しますが、出力例は次のとおりです。

/Users/matthew/Library/Frameworks/Lgi.framework/Versions/A/Lgi+0x2473d(LgiStackTrace+0x5d) [0x102c73d]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2a006(tart+0x28e72) [0x2b006]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2f438(tart+0x2e2a4) [0x30438]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x35e9c(tart+0x34d08) [0x36e9c]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x1296(tart+0x102) [0x2296]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x11bd(tart+0x29) [0x21bd]

共有オブジェクトのメソッド名は正しく取得されていますが、メインアプリのメソッド名は取得されていません。それらは単に「tart」(または「start」から最初の文字を引いたもの)にマップされます。

理想的には、その時点で行番号とメソッド名が必要です。しかし、初心者向けの正しい関数/メソッド名に落ち着きます。Linux では、独自の命令セットを持つプライベート ELF ブロック用に独自のパーサーを作成する必要があると聞いています。怖いですね。

とにかく、誰かがこのコードを整理して、メソッド名を正しく取得できますか?

4

1 に答える 1

13

OS X のどのリリースをターゲットにしていますか。Mac OS X 10.5 以降で実行している場合は、backtrace() および backtrace_symbols() libraray 呼び出しを使用できます。それらは execinfo.h で定義されており、いくつかのサンプル コードを含むマンページがあります。

編集:

コメントで、Tiger で実行する必要があると述べました。おそらく、Libc からの実装をアプリに含めることができます。ソースは、Apple のオープンソース サイトから入手できます。関連ファイルへのリンクは次のとおりです。

于 2008-11-14T15:59:45.597 に答える