【C++23】std::stacktraceでスタックトレース(関数呼び出し履歴)を取得する方法

目次

はじめに

プログラムのデバッグ中、特にエラーが発生した際に、「どの関数が、どの順番で呼び出されて、今の場所にたどり着いたのか」という呼び出し履歴を知りたい場面は非常に多くあります。この関数の呼び出し階層の情報を「スタックトレース」と呼びます。

従来、C++でスタックトレースを取得するには、OS固有のAPIを使ったり、サードパーティのライブラリを使ったりする必要があり、非常に複雑でした。

この問題を解決するために、C++23では std::stacktrace という、スタックトレースを標準機能として取得・操作するためのクラスが導入されました。

この記事では、std::stacktrace を使って、現在の関数呼び出し履歴を簡単に取得し、表示する方法を解説します。


【前提】C++23とは?

C++23(シーピープラスにーさん)は、2023年に正式化されたC++言語の比較的新しい規格です。std::stacktrace はこのC++23で追加された機能のため、利用するにはC++23に対応した最新のコンパイラ(と、その機能を有効にするための設定)が必要になります。


std::stacktrace を使ったサンプルコード

このコードは、functionAfunctionBfunctionC という順番で関数を呼び出し、一番深い階層の functionC の中で、そこに至るまでのスタックトレースを取得して表示します。

完成コード

#include <iostream>
#include <stacktrace> // std::stacktrace を使うために必要

using namespace std;

// 3番目に呼ばれる関数
void functionC() {
    cout << "--- functionC に到達 ---" << endl;
    
    // 現在のスタックトレースを取得して、標準エラー出力に出力する
    cout << stacktrace::current() << endl;
}

// 2番目に呼ばれる関数
void functionB() {
    functionC();
}

// 最初に呼ばれる関数
void functionA() {
    functionB();
}


int main() {
    functionA();
    return 0;
}

実行結果(コンパイラや環境により出力形式は異なります)

--- functionC に到達 ---
 0# functionC() at main.cpp:11
 1# functionB() at main.cpp:17
 2# functionA() at main.cpp:22
 3# main at main.cpp:28
 ... (以降、プログラムの起動に関するシステム関数が続く)

コードの解説

#include <stacktrace>

std::stacktrace を利用するには、このヘッダーファイルをインクルードする必要があります。

cout << stacktrace::current() << endl;

これが、スタックトレースを取得・表示する核心部分です。

  • stacktrace::current(): この静的メンバ関数を呼び出すと、その呼び出し時点でのスタックトレース情報を含む std::stacktrace オブジェクトが生成されます。
  • cout << ...: stacktrace オブジェクトは、cout のような出力ストリームに直接渡せるように設計されており、人間が読みやすい形式で整形されたスタックトレースを出力してくれます。

実行結果を見ると、functionCfunctionB から、functionBfunctionA から、そして functionAmain から呼び出された、という呼び出しの履歴が、下から上へと順番に表示されていることが分かります。


まとめ

今回は、C++23で導入された std::stacktrace を使って、プログラムのデバッグに非常に役立つスタックトレース情報を簡単に取得する方法を解説しました。

  • <stacktrace> ヘッダーをインクルードする。
  • std::stacktrace::current() を呼び出すだけで、その時点の呼び出し履歴が取得できる。

例外処理の catch ブロックなどで stacktrace::current() を使えば、エラーが発生した箇所の呼び出し階層をログに記録するといった、より高度で実用的なエラーハンドリングを実装することができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次