1

プログラム内からコール スタックを出力しようとしています。残念ながら、glibc backtrace() を呼び出すと、常に 1 つのレコード (現在の関数のアドレス) しか返されません。私はsh4-linuxに取り組んでいますが、これがおそらく問題の原因です。x86 アーキテクチャで印刷するのに問題はありませんでした。

コード例:

#include <string>
#include <iostream>
#include <execinfo.h>

const int maxCalls = 666;

void baz()
{
        void *buffer[ maxCalls ];
        int stackSize = backtrace( buffer, maxCalls );

        char **symbols = backtrace_symbols( buffer, stackSize );

        std::string str;

        for( unsigned i = 0; i < stackSize; ++i )
        {
                str+= symbols[i];
        }
        free( symbols );
        std::cout << str<< std::endl;
}

void bar()
{
        baz();
}

void foo()
{
        bar();
}

int main(int argc, char **argv)
{
        foo();
        return 0;
}

によってコンパイルされました:

sh4-linux-g++ test.cpp -g -c -o test.o
sh4-linux-g++ test.o -g -rdynamic -o test

編集: 実際、このコードは正常に動作します。おそらく、何らかのコンパイラ フラグが実際のプロジェクトでこの動作を引き起こす可能性があります。

コンパイラ フラグは次のとおりです。-g -O0 -pipe -fpermissive -frtti -fno-exceptions -ffunction-sections

リンカー フラグ:-lpthread -g -rdynamic -Wl,-gc-sections -Wl,--start-group {Files here} -Wl,--end-group --verbose -Xlinker -lm

EDIT2 :どのフラグが原因であるかがわかりました: -fno-exceptions. 誰でも理由を教えてもらえますか? そして、このフラグをスキップせずに修復できるとしたら?

EDIT3:まあ、気にしないでください。実はこのフラグは省略できるようです。

4

3 に答える 3

1

「stackSize = 1;」を削除してみてください。

于 2010-11-28T07:37:39.980 に答える
1

glibc へのパッチが必要です。ここを見てください。

パッチに記載されているように、バックトレースを使用するユーザー アプリケーションは、"-fexceptions" を指定してコンパイルする必要があります。アドレスの完全なシンボル解決が必要な場合は、「-rdynamic」も必要です。

于 2011-05-19T21:58:29.853 に答える
0

コンパイラがこれらの関数をインライン化している可能性があります。-O0オプションを使用して再コンパイルしてみてください。

于 2010-11-25T20:48:15.087 に答える