235

例外がスローされた場合に、スタック トレースをユーザーに報告する方法が必要です。これを行う最善の方法は何ですか?大量の余分なコードが必要ですか?

質問に答えるには:

できれば携帯できるようにしたいです。エラーが発生した場合にユーザーがスタック トレースをコピーしてメールで送信できるように、情報がポップアップ表示されるようにします。

4

16 に答える 16

82

アンドリュー・グラントの答えは、少なくともGCCではスロー関数のスタックトレースを取得するのに役立ちませ.throwステートメントは現在のスタックトレースを単独で保存せず、catchハンドラーはスタックトレースにアクセスできないためです.その点はもう。

GCC を使用してこれを解決する唯一の方法は、throw 命令の時点でスタック トレースを生成し、それを例外オブジェクトに保存することです。

もちろん、このメソッドでは、例外をスローするすべてのコードがその特定の Exception クラスを使用する必要があります。

2017 年 7 月 11 日更新: 役立つコードについては、http://stacktrace.sourceforge.net を指す cahit beyaz の回答ご覧ください。まだ使用していませんが、有望に見えます。

于 2014-11-12T09:16:49.103 に答える
79

プラットフォームによって異なります。

GCC ではかなり簡単です。詳細については、この投稿を参照してください。

MSVCでは、Windows に必要なすべての基になる API 呼び出しを処理するStackWalkerライブラリを使用できます。

この機能をアプリに統合する最善の方法を見つける必要がありますが、記述する必要があるコードの量は最小限に抑える必要があります。

于 2009-03-27T22:55:57.273 に答える
16

Unix: バックトレース

Mac: バックトレース

Windows: CaptureBackTrace

于 2013-08-30T22:26:13.507 に答える
5

私の知る限り、libunwind は非常に移植性が高く、これまでのところ、より使いやすいものは見つかりませんでした。

于 2012-12-19T17:26:22.587 に答える
3

私も同様の問題を抱えており、移植性は気に入っていますが、必要なのは gcc サポートだけです。gcc では、execinfo.h とバックトレース呼び出しが利用できます。関数名を分解するために、Bingmann 氏は優れたコードを提供しています。例外でバックトレースをダンプするには、コンストラクターでバックトレースを出力する例外を作成します。これがライブラリでスローされた例外で機能することを期待していた場合、バックトレース例外が使用されるように再構築/リンクが必要になる場合があります。

/******************************************
#Makefile with flags for printing backtrace with function names
# compile with symbols for backtrace
CXXFLAGS=-g
# add symbols to dynamic symbol table for backtrace
LDFLAGS=-rdynamic
turducken: turducken.cc
******************************************/

#include <cstdio>
#include <stdexcept>
#include <execinfo.h>
#include "stacktrace.h" /* https://panthema.net/2008/0901-stacktrace-demangled/ */

// simple exception that prints backtrace when constructed
class btoverflow_error: public std::overflow_error
{
    public:
    btoverflow_error( const std::string& arg ) :
        std::overflow_error( arg )
    {
        print_stacktrace();
    };
};


void chicken(void)
{
    throw btoverflow_error( "too big" );
}

void duck(void)
{
    chicken();
}

void turkey(void)
{
    duck();
}

int main( int argc, char *argv[])
{
    try
    {
        turkey();
    }
    catch( btoverflow_error e)
    {
        printf( "caught exception: %s\n", e.what() );
    }
}

これを gcc 4.8.4 でコンパイルして実行すると、C++ 関数名がきれいに分解されたバックトレースが生成されます。

stack trace:
 ./turducken : btoverflow_error::btoverflow_error(std::string const&)+0x43
 ./turducken : chicken()+0x48
 ./turducken : duck()+0x9
 ./turducken : turkey()+0x9
 ./turducken : main()+0x15
 /lib/x86_64-linux-gnu/libc.so.6 : __libc_start_main()+0xf5
 ./turducken() [0x401629]
于 2016-07-09T14:59:21.760 に答える
3

Windows では、BugTrapを確認してください。元のリンクにはありませんが、CodeProject で引き続き利用できます。

于 2010-01-06T22:56:55.147 に答える
2

次のコードは、例外がスローされた直後に実行を停止します。終了ハンドラーと共に windows_exception_handler を設定する必要があります。これを MinGW 32 ビットでテストしました。

void beforeCrash(void);

static const bool SET_TERMINATE = std::set_terminate(beforeCrash);

void beforeCrash() {
    __asm("int3");
}

int main(int argc, char *argv[])
{
SetUnhandledExceptionFilter(windows_exception_handler);
...
}

windows_exception_handler 関数については、次のコードを確認してください: http://www.codedisqus.com/0ziVPgVPUk/exception-handling-and-stacktrace-under-windows-mingwgcc.html

于 2015-06-11T20:01:40.327 に答える
2

Poppyは、スタック トレースだけでなく、パラメーター値、ローカル変数など、クラッシュにつながるすべてのものを収集できます。

于 2014-10-23T13:09:18.940 に答える
1

Cpp-tool ex_diag - easyweight、マルチプラットフォーム、最小限のリソース使用、シンプルで柔軟なトレース。

于 2013-06-16T18:56:38.067 に答える