goto でスコープを抜けるとクラスのデストラクタが呼び出されない現象に遭遇
ここ一週間ほど仕事でハマった現象。
以下サンプル。
class Foo { public: Foo() { puts("constructor"); } ~Foo() { puts("destructor"); } }; int main(int argc, char *argv[]) { int flag = 0; L0: if (flag++ == 0) goto L1; else goto L2; L1: { Foo foo; goto L0; } L2: return 0; }
auto 変数のクラスインスタンスはスコープを抜ける際にデストラクタが呼ばれるが、goto でスコープを抜ける場合もデストラクタが呼ばれることは C++ の言語仕様として保証されている、らしい。実際そのように動作している。
goto では、デストラクタは呼ばれる - masugata_kの日記
ただ、どのような条件かはわからないが、デストラクタが呼び出されないことがある。アセンブラやその他の中間コードを調べたところ、確かにデストラクタが実行されているコードがそれらに存在しない。
何故デストラクタが呼び出されないのか原因が良くわからない。使用しているコンパイラのバグではないかと考えているが、確証が持てない。とりあえず回避方法は以下のように行ったが、根本的ではないのでモヤモヤする。
class Foo { public: Foo() { puts("constructor"); } ~Foo() { puts("destructor"); } }; int main(int argc, char *argv[]) { int flag = 0; L0: if (flag++ == 0) goto L1; else goto L2; L1: { { // もうひとつブロックをネストして、 // こちらのブロックのスコープでデストラクタを呼び出す Foo foo; } goto L0; } L2: return 0; }