namespace std {
void observable_checkpoint() noexcept;
}
概要
観測可能チェックポイント (observable checkpoint) を設置する。
C++では未定義動作を含むプログラムに対して、コンパイラは未定義動作が「将来」発生することを根拠に、それより「前」の操作を削除・変更する最適化を行うことが許容される。これは「タイムトラベル最適化」と呼ばれる。
例として以下のコードでは、(2)で未定義動作があるため、(1)の出力すら省略される可能性がある:
#include <cstdio>
int main() {
std::printf("Hello, "); // (1) 出力
int* p = nullptr;
*p = 42; // (2) 未定義動作(nullポインタのデリファレンス)
std::printf("World!\n"); // (3) 出力
}
std::observable_checkpoint()を呼び出すと、その時点で観測可能チェックポイントが設置される。観測可能チェックポイントより前に完了した操作の観測可能な動作は、その後に発生する未定義動作によって遡って無効化されないことが保証される。これにより、タイムトラベル最適化を抑止できる:
#include <cstdio>
#include <utility>
int main() {
std::printf("Hello, "); // (1) 出力
std::observable_checkpoint(); // ここまでの観測可能な動作を保護
int* p = nullptr;
*p = 42; // (2) 未定義動作
std::printf("World!\n"); // (3) 出力
}
この場合、std::observable_checkpoint()によって(1)の出力"Hello, "が保護され、(2)の未定義動作があっても遡って消去されない。
std::observable_checkpoint()の明示的な呼び出しに加え、以下の操作も暗黙的に観測可能チェックポイントを設置する:
- C標準の入出力関数(
std::printf()、std::fwrite()など)のうち、ファイルへのデータ書き込みを行う関数呼び出しからの復帰 std::basic_filebufのオーバーフロー操作(出力シーケンスへの書き込み完了時)- Unicode出力時の
std::print()/std::println()の内部出力関数std::vprint_unicode()によるターミナルへの書き込み(<ostream>版および<print>版)
上記の例ではstd::printf()がC標準の入出力関数であるため、(1)の呼び出しの復帰が暗黙の観測可能チェックポイントとなり、"Hello, "の出力は(2)の未定義動作によって遡って消去されない。
効果
観測可能チェックポイントを設置する。
例外
投げない
備考
std::observable_checkpoint()の呼び出し自体は観測可能な動作ではない。コンパイラはこの関数を組み込み関数 (intrinsic) として実装でき、最適化後にゼロ命令のコードを生成できるvolatileアクセスは暗黙の観測可能チェックポイントではない。volatileアクセスの順序保証は従来の happens before 規則に従う- この関数はフリースタンディング環境でも使用可能である
例
基本的な使い方
この例では、iが10以上になるとtable[i]で範囲外アクセスの未定義動作が発生する。しかしstd::printf()はC標準の入出力関数であり、呼び出しの復帰が暗黙の観測可能チェックポイントとなる。そのため、iが0から9までの反復で出力された"processing 0"から"processing 9"は、その後の未定義動作によって遡って消去されることはない。
出力例
processing 0
processing 1
processing 2
processing 3
processing 4
processing 5
processing 6
processing 7
processing 8
processing 9
processing 10
processing 11
明示的なチェックポイントの設置
出力例
sum = 15
バージョン
言語
- C++26
処理系
- Clang: 22 ❌
- GCC: 15 ❌
- Visual C++: 2026 Update 2 ❌