从专门方法捕获异常

时间:2013-10-21 11:20:47

标签: c++ templates exception c++11

让我们考虑以下三个文件。

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

第二次测试:如果我们在for(auto it:storage)文件中发表评论tclass.h,程序将在main函数中捕获异常。 WAT 为什么呢?是否试图迭代空向量导致堆栈损坏?

第三次测试:让我们取消注释for(auto it:storage)行并将方法专精从spec.cpp移到main.cpp。然后在wrapper中捕获异常。怎么可能,为什么可能的内存损坏不会影响这种情况呢?

我还尝试使用不同的优化级别和-g编译它,但结果是相同的。

然后我在Windows 7 x64,VS2012 express上尝试了它,使用x64版本的cl.exe进行编译,没有额外的命令行参数。在第一次测试时,这个程序没有输出,所以我认为它只是默默地崩溃,所以结果与Linux版本相似。对于第二次测试,它不再产生输出,因此结果与Linux不同。对于第三次测试,结果与Linux结果类似。

此代码中是否有任何错误,导致此类行为?可能第一次测试的结果是由编译器中的可能错误引起的?

1 个答案:

答案 0 :(得分:2)

使用您的代码,我使用gcc 4.7.1:

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

您可以通过将.h中的专业化声明为:

来更正您的代码

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