让我们考虑以下三个文件。
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;
};
规范.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;
}
主.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
函数中捕获异常。笏为什么?是否是由于尝试遍历空向量而导致的堆栈损坏?
第三个测试:让我们取消注释该for(auto it:storage)
行并将方法专业化从spec.cpp
移至main.cpp
。然后异常被捕获在wrapper
. 这怎么可能,为什么可能的内存损坏不会影响这种情况?
我也尝试用不同的优化级别和 with 来编译它-g
,但结果是一样的。
然后我在 Windows 7 x64、VS2012 express 上进行了尝试,使用 x64 版本的 cl.exe 进行编译,没有额外的命令行参数。在第一次测试时,这个程序没有输出,所以我认为它只是默默地崩溃了,所以结果与 Linux 版本相似。对于第二次测试,它再次没有输出,因此结果与 Linux 不同。第三次测试的结果与 Linux 的结果相似。
此代码中是否有任何错误,因此它们可能导致这种行为?第一次测试的结果可能是由编译器中可能的错误引起的吗?