C++のスタック巻き戻し(スタックアンワインディング)とは?仕組みをサンプルコードで解説
本記事では、C++における「スタック巻き戻し(Stack Unwinding:スタックアンワインディング)」の意味と動作について詳しく解説します。
スタック巻き戻しの基本概念
プログラム内で関数を呼び出すと、その呼び出し元の情報(リターンアドレスなど)がコールスタック上に保存されます。そして、関数から戻るときには、その情報がスタックから取り除かれ(ポップされ)、処理は中断していた箇所から再開されます。
スタック巻き戻しとは、実行時に関数呼び出しスタックのエントリを順次取り除いていくプロセスのことです。このスタック要素の除去には、例外を利用することができます。内部の関数から例外がスローされると、その時点でスタック上のエントリがすべて破棄され、制御は例外を捕捉した呼び出し元の関数へと一気に戻ります。
それでは、実際のコード例を通して、スタック巻き戻しの挙動を確認してみましょう。
サンプルコード
#include <iostream>
using namespace std;
void function1() { // 例外をスローする関数
cout << "\n Entering into function 1";
throw 100;
cout << "\n Exiting function 1";
}
void function2() { // function1 を呼び出す関数
cout << "\n Entering into function 2";
function1();
cout << "\n Exiting function 2";
}
void function3() { // function2 を呼び出し、
// function1 が投げた例外を処理する関数
cout << "\n Entering function 3 ";
try {
function2(); // function2 の実行を試みる
}
catch(int i) {
cout << "\n Caught Exception: " << i;
}
cout << "\n Exiting function 3";
}
int main() {
function3();
return 0;
}
実行結果
Entering function 3 Entering into function 2 Entering into function 1 Caught Exception: 100 Exiting function 3
実行結果のポイント
この実行結果から、まず function3 の情報がスタックに保存され、次に function2 へ、さらに function1 へと制御が移っていく様子がわかります。その後、function1 内で例外が発生すると、スタック上のエントリがすべて巻き戻されて破棄され、制御は function3 の catch ブロックへと戻り、例外が捕捉されます。
注目すべき点として、「Exiting function 1」や「Exiting function 2」という出力が表示されていません。これは、throw 文が実行された時点でそれ以降の処理がスキップされ、スタックが巻き戻されるためです。これこそがスタック巻き戻しの典型的な動作です。
補足:動的例外指定について
元のコードでは throw(int) という動的例外指定(dynamic exception specification)が使われていましたが、この構文は C++11 で非推奨となり、C++17 で廃止されています。現代の C++ では、例外の型指定が必要な場合は noexcept 指定子を使うか、単に例外仕様を記述しないのが一般的です。上記のサンプルコードは、その点を考慮して修正したものを掲載しています。
-
C++で解く「回転関数(Rotate Function)」問題 ― 漸化式でO(n)高速化する方法
問題の概要 長さ n の整数配列 A が与えられます。Bk を「配列 A を時計回りに k 個分回転させた配列」とするとき、回転関数 F(k) は次のように定義されます。 F(k) = 0 × Bk[0] + 1 × Bk[1] + … + (n−1) × Bk[n−1] このとき、F(0)、F(1)、…、F(n−1) の中から最大値を求めるのが本問題の目的です。 具体例:A = [4, 3, 2, 6] の場合 回転ごとの値は以下のように計算できます。 F(0) = (0×4) + (1×3) + (2×2) + (3×6) = 0 + 3 + 4 + 18 = 25 F(1) = (0×
-
C++ STLのスタック(stack)徹底解説!LIFO構造の基本操作とサンプルコード
C++ STLにおけるスタック(stack)は、LIFO(Last In First Out:後入れ先出し)構造として実装されるコンテナです。LIFOとは「最後に入れたものが最初に取り出される」という意味で、本を一冊ずつ積み上げた山をイメージすると理解しやすいでしょう。一番上に置いた本(=最後に挿入された要素)が最初に取り出されることから、この構造はLIFOと呼ばれています。 スタックで使える主な操作 1. top() – 最上位要素の取得 スタックの最上位(先頭)にある要素への参照を返します。要素自体は削除されません。 構文:name_of_stack.top() 引数:なし 戻り値:ス