4

Python では、例外が発生すると、キャッチがなくても、どのファイルでエラーが発生したかに関する詳細情報を取得できます。

def hello():
    raise Exception;

hello() 

Execution result >>

Traceback (most recent call last):
  File "exceptionExample.py", line 4, in <module>
    hello()
  File "exceptionExample.py", line 2, in hello
    raise Exception;
Exception

C++ では、この情報はあまり役に立ちません。

#include <iostream>

using namespace std;

class Error
{
};

int value()
{
    throw Error();
}

int main(int argc, char *argv[]) {
    value();
}

>>

terminate called after throwing an instance of 'Error'
Run Command: line 1: 52772 Abort trap: 6           ./"$2" "${@:3}"

どのモジュールでどの行からエラーが発生したかについて、より詳細な情報を C++ に提供させるにはどうすればよいですか?

catch句なしで使用したいと思います。

4

4 に答える 4

3

__FILE__との__LINE__定義を例外メッセージで使用できます。

例えば:

#include <stdexcept>

class Error : public std::runtime_error
{
  public:
    Error (const std::string &message)
      : std::runtime_error(message)
    {}

};

int value()
{
    std::stringstream ss;
    ss << "Issues at " << __FILE__ << " on line " << __LINE__;
    throw Error(ss.str());
}

この例では、(メッセージを文字列として渡すためのコンストラクターを持っている)Error継承を行いました...std::runtime_error

さらに、この SO の質問を見てください: Global Exception Handling - 関数の使用に関する回答に注意してくださいset_terminate。これにより、メッセージが希望どおりに出力されるようにするグローバル ハンドラーをインストールできます。set_terminate()に関する情報を次に示します。

Python は、キャッチされていない例外のスタック トレースを提供します。私が提供した答えは、ファイルと行番号のみを示しています。スタック トレースが必要な場合は、C++ でこれを行う方法に関するアドバイスを提供する他の SO の質問をいくつかのコメント作成者が参照しています。ただし、この問題に対する非標準の解決策には注意してください。

于 2013-06-14T15:21:08.430 に答える
0

スタック トレースを取得する移植可能な方法はありません。秘訣は、関数コンテキストでオブジェクトを使用して情報を保存することです。

struct StackTraceInfo {
    const char *filename;
    int line;
    static std::vector<StackTraceInfo *> stack;
    StackTraceInfo(const char *filename, int line) :
      filename(filename), line(line)
    {
        stack.push_back(this);
    }

    ~StackTraceInfo()
    {
        stack.pop_back();
    } 
};

#define ENTER StackTraceInfo(__FILE__, __LINE__) sinfo_;

すべての関数ENTERで、本体の最初に行を追加するだけです

int foo() {
    ENTER
    ....
    return 42;
}

スローする前に例外が発生した場合は、グローバルStackTraceInfo::stackベクトルの内容を使用して現在のスタック トレースを保存し、メッセージを表示するユーザーがこの情報にアクセスできるようにする必要があります。スタックはその時点ですでにアンワインドされているため、例外ハンドラーのスタック情報にアクセスできないことに注意してください。

また、アプリケーションがマルチスレッド化されている場合は、グローバルの代わりにスレッド ローカル ストレージを使用して、スレッドごとに個別のスタックを使用する必要があることに注意してください。

于 2013-06-14T15:41:08.327 に答える
0

標準の C++11を使用すると、ありがたいことに Python のバックトレースに非常によく似たものを取得できます。

std::nested_exceptionstd::throw_with_nested

StackOverflow hereおよびhereで説明されています。ネストされた例外を再スローする適切な例外ハンドラーを記述するだけで、デバッガーや面倒なログを必要とせずに、コード内の例外のバックトレースを取得する方法について説明されています。

バックトレースに表示するすべての関数をラップする必要があり、ソースの場所情報を自動的に追加するには、try/catch非標準マクロ ( __FILE____func__、 ) が必要であることに注意してください。__LINE__

任意の派生例外クラスでこれを行うことができるため、このようなバックトレースに多くの情報を追加できます! また、GitHub の MWE「トレース」ライブラリもご覧ください。バックトレースは次のようになります。

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
于 2019-12-24T16:32:18.117 に答える
0

例外が作成されたときにスタック トレースをラップするように例外を作成できます。スタック トレースのログはセキュリティ上の問題になる可能性があるため、デバッグ モードでのみログに記録するように注意してください。

また、デバッガーを使用すると役立つ場合があります。

于 2013-06-14T15:21:49.843 に答える