次の 3 つのファイルについて考えてみましょう。
tclass.h:
#include <iostream>
#include <vector>
template<typename rt>
class tclass
{
public:
void wrapper()
{
//Storage is empty
for(auto it:storage)
{
}
try
{
thrower();
}
catch(...)
{
std::cout << "Catch in wrapper\n";
}
}
private:
void thrower(){}
std::vector<int> storage;
};
spec.cpp:
#include "tclass.h"
//The exact type does not matter here, we just need to call the specialized method.
template<>
void tclass<long double>::thrower()
{
//Again, the exception may have any type.
throw (double)2;
}
main.cpp:
#include "tclass.h"
#include <iostream>
int main()
{
tclass<long double> foo;
try
{
foo.wrapper();
}
catch(...)
{
std::cerr << "Catch in main\n";
return 4;
}
return 0;
}
Linux x64、gcc 4.7.2 を使用しています。ファイルは次のコマンドでコンパイルされます。
g++ --std=c++11 *.cpp
最初のテスト: 上記のプログラムを実行すると、次のように表示されます。
terminate called after throwing an instance of 'double'
Aborted
2 番目のテスト: ファイル内でコメントfor(auto it:storage)
するtclass.h
と、プログラムはmain
関数内で例外をキャッチします。なに?空のベクターを反復しようとしたために発生したスタックの破損ですか?
3 番目のテスト:for(auto it:storage)
行のコメントを解除し、メソッドの特殊化を からspec.cpp
に移動しmain.cpp
ます。次に、例外がキャッチされwrapper
ます。どのように可能であり、メモリ破損の可能性がこのケースに影響しないのはなぜですか?
また、さまざまな最適化レベルと を使用してコンパイルしようとしまし-g
たが、結果は同じでした。
次に、Windows 7 x64、VS2012 Express で試し、追加のコマンド ライン引数なしで cl.exe の x64 バージョンでコンパイルしました。最初のテストでは、このプログラムは出力を生成しなかったので、黙ってクラッシュしただけだと思うので、結果は Linux 版と似ています。2 番目のテストでは、再び出力が生成されなかったため、結果は Linux とは異なります。3 番目のテストでは、結果は Linux の結果と同様でした。
このコードにエラーがあるため、そのような動作につながる可能性がありますか? 最初のテストの結果は、コンパイラのバグが原因である可能性がありますか?