1

次の 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 の結果と同様でした。

このコードにエラーがあるため、そのような動作につながる可能性がありますか? 最初のテストの結果は、コンパイラのバグが原因である可能性がありますか?

4

1 に答える 1

2

あなたのコードで、私はgcc 4.7.1を持っています:

spec.cpp:6: multiple definition of 'tclass<long double>::thrower()'

.h の特殊化を次のように宣言することで、コードを修正できます。

template<> void tclass<long double>::thrower();

于 2013-10-21T13:28:44.443 に答える