コンピューティングにおいて、スタック トレース(スタック バックトレース[1]またはスタック トレースバック[2]とも呼ばれる) は、プログラムの実行中のある時点でのアクティブなスタック フレームのレポートです。プログラムが実行されると、多くの場合、メモリはスタックとヒープの2 つの場所に動的に割り当てられます。メモリはスタック上に連続的に割り当てられますが、ヒープ上には割り当てられないため、それらの名前が反映されています。スタックはプログラミング構造を指すこともあるため、区別するために、このスタックはプログラムの関数呼び出しスタックと呼ばれます。技術的には、スタック上にメモリ ブロックが割り当てられると、その前に割り当てられた他のメモリ ブロックが存在する可能性があるため、簡単に削除することはできません。プログラムで関数が呼び出されるたびに、アクティベーション レコードと呼ばれるメモリ ブロックが呼び出しスタックの上部に割り当てられます。一般に、アクティベーション レコードには関数の引数とローカル変数が格納されます。アクティベーション レコードに正確に何が含まれるか、どのように配置されるかは、呼び出し規約によって決まります。
プログラマーは、インタラクティブ デバッグや事後デバッグ中にスタック トレースを使用するのが一般的です。エンド ユーザーは、エラー メッセージの一部としてスタック トレースが表示されるのを確認して、それをプログラマーに報告することができます。
スタック トレースを使用すると、スタック トレースが生成される時点まで、呼び出されたネストされた関数のシーケンスを追跡できます。事後分析のシナリオでは、これは障害が発生した関数 (必ずしも原因ではない) まで拡張されます。兄弟呼び出しはスタック トレースに表示されません。
言語サポート
Java [3]やC# [4]を含む多くのプログラミング言語には、システムコールを介して現在のスタックトレースを取得するためのサポートが組み込まれています。 が のstd::stacktraceコンテナとして標準ライブラリに追加される前はstd::stacktrace_entry、C++23より前ではこれを行うためのサポートが組み込まれていませんでしたが、C++ ユーザーは (たとえば) stacktraceライブラリを使用してスタックトレースを取得できます。JavaScript では、例外は、スローされた場所からのスタックを含むプロパティ
を保持します。stack
パイソン
たとえば、次のPythonプログラムにはエラーが含まれています。
定義( ):
私 = 0
j = b ( i )
戻る
定義 b ( z ):
5 の
z == 0の場合:
c () 関数
k + z を返す
デフ c ():
エラー()
()
標準の Python インタープリターでプログラムを実行すると、次のエラー メッセージが生成されます。
トレースバック (最新の呼び出しが最後):
ファイル"file.py"、行15、<module>内
a ()
ファイル"file.py"、行3 、 a内j = b ( i )
ファイル"file.py"、行9、b内c ()
ファイル"file.py"、行13、c内error () NameError :名前 'error' は定義されていません
スタック トレースは、エラーが発生した場所、つまりc関数を示しています。また、c関数が によって呼び出されb、それが によって呼び出され、それがプログラムの 15 行目 (最後の行) のコードによって呼び出されたことが示されています。これら 3 つの関数のそれぞれのアクティベーション レコードは、関数がスタックの一番下を占め、関数がスタックの一番上を占める
aようにスタックに配置されます。ac
ジャワ
Javaでは、スタックトレースを手動でダンプすることができます。Thread.dumpStack()[5]次の入力を取ります。
パブリッククラスMain {
パブリック静的voidメイン(文字列引数[] ){
デモ();
}
静的voidデモ(){
デモ1 ();
}
静的voidデモ1 (){
デモ2 ();
}
静的voidデモ2 (){
デモ3 ();
}
静的voidデモ3 (){
スレッド.dumpStack ( );
}
}
例外は関数を降順でリストするため、最も内側の呼び出しが最初になります。
java . lang .例外:スタックトレースat java . lang . Thread . dumpStack ( Thread . java : 1336 ) at Main . demo3 ( Main . java : 15 ) at Main . demo2 ( Main . java : 12 ) at Main . demo1 ( Main . java : 9 ) at Main . demo ( Main . java : 6 ) at Main . main ( Main . java : 3 )
C および C++
CとC++ ( C++23以前)はどちらもスタック トレースを取得するためのネイティブ サポートを持っていませんが、glibcやboostなどのライブラリがこの機能を提供しています。[6] [7]これらの言語では、一部のコンパイラ最適化により、実行時に回復できるコール スタック情報が妨げられることがあります。たとえば、インライン化によってスタック フレームが失われる場合や、末尾呼び出しの最適化によってスタック フレームが別のスタック フレームに置き換えられる場合、フレーム ポインタの削除によってコール スタック分析ツールがコール スタックの内容を正しく解釈できなくなる場合があります。[6]
たとえば、glibc のbacktrace()関数は、プログラム関数とメモリ アドレスを含む出力を返します。
./a.out ( ) [ 0x40067f ] ./a.out ( ) [ 0x4006fe ] ./a.out ( ) [ 0x40070a ] / lib / x86_64 - linux - gnu / libc.so.6 ( __ libc_start_main + 0xf5 ) [ 0x7f7e60738f45 ] ./a.out ( ) [ 0x400599 ]
C++23以降では、静的メンバー関数によって返される値を印刷することで、スタックトレースを手動でダンプすることができますstd::stacktrace::current()。[8]
std :: cout << std :: stacktrace :: current () << '\n' ;
さび
Rust には 2 種類のエラーがあります。パニックマクロを使用する関数は「回復不能」であり、現在のスレッドはスタックの巻き戻しによって汚染されます。を返す関数はstd::result::Result「回復可能」であり、適切に処理できます。[9]ただし、回復可能なエラーは手動で追加され、実行時エラーの結果ではないため、スタック トレースを生成できません。
2021年6月現在、Rustは回復不能なエラーのスタックトレースを実験的にサポートしています。Rustはスレッドパニック時にstderrへの出力をサポートしていますが、RUST_BACKTRACE 環境変数を設定して有効にする必要があります。[10]
有効にすると、このようなバックトレースは以下のように表示され、最新の呼び出しが最初になります。
スレッド' main ' が' execute_to_panic 'でパニックになりました。main . rs : 3スタックバックトレース:
0 : std :: sys :: imp :: backtrace :: tracing :: imp :: unwind_backtrace 1 : std :: panicking :: default_hook :: {{ closure } } 2 : std :: panicking :: default_hook 3 : std :: panicking :: rust_panic_with_hook 4 : std :: panicking :: begin_panic 5 : futures :: task_impl :: with 6 : futures :: task_impl :: park .. .
参照
参考文献
- ^ 「libc マニュアル: バックトレース」。gnu.org。2014年7 月 8 日閲覧。
- ^ "traceback — スタックトレースバックを印刷または取得する". python.org . 2014年7月8日閲覧。
- ^ 「スレッド (Java SE 16 & JDK 16)」。Java Platform Standard Edition および Java Development Kit バージョン 16 API 仕様。2021 年 3 月 4 日。2021 年 7 月 4 日閲覧。
- ^ 「Environment.StackTrace プロパティ (システム)」。Microsoft Docs 2021-05-07 。2021-07-04に取得。
- ^ 「スレッド (Java Platform SE 8)」。docs.oracle.com 。2021年6月15日閲覧。
- ^ ab "Backtraces (The GNU C Library)". www.gnu.org . 2021年6月15日閲覧。
- ^ 「Getting Started - 1.76.0」www.boost.org . 2021年6月15日閲覧。
- ^ 「ワーキングドラフト、プログラミング言語 C++ の標準」(PDF) . open-std.org . ISO/IEC. 2021-10-23. p. 766.
- ^ 「rustonomicon のアンワインド - Rust」。doc.rust-lang.org。
- ^ "std::backtrace - Rust". doc.rust-lang.org . 2021年6月15日閲覧。
