我写了一个非常简单的解决方案,但是有人笑了,发现了一个缺陷,如下所示http://ideone.com/IcWMEf
#include <iostream>
#include <ostream>
#include <functional>
#include <exception>
using namespace std;
// Wrong scope(failure)
class FailBlockT
{
typedef function<void()> T;
public:
T t;
FailBlockT(T t)
{
this->t=t;
}
~FailBlockT()
{
if (std::uncaught_exception())
{
t();
}
}
};
struct Test
{
~Test()
{
try
{
FailBlockT f([]()
{
cout << "failure" << endl;
});
// there is no any exception here, but "failure" is printed.
// See output below
}
catch(...)
{
cout << "some exception" << endl;
}
}
};
int main()
{
try
{
Test t;
throw 1;
}
catch(int){}
return 0;
}
总之,问题是我的代码在std::uncaught_exception()
处。当引发异常并执行常规析构函数时。如果我使用范围失败,它将查看std::uncaught_exception()
并认为对象范围由于异常而丢失,而不是简单地退出范围。
我想不出任何好的解决方案,通常情况下,VS离开范围并在其中抛出异常。是的,我知道在dtors中扔是一个坏主意,但这就是为什么我未能注意到此问题的原因,因为我从未抛出异常。
我该如何区分/解决这个问题?
目前已在{Clang 3.2,GCC 3.4.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7,MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012} x {x32,x64}上进行了测试。在C ++ 11中,以下语法为available:
try { int some_var=1; cout << "Case #1: stack unwinding" << endl; scope(exit) { cout << "exit " << some_var << endl; ++some_var; }; scope(failure) { cout << "failure " << some_var << endl; ++some_var; }; scope(success) { cout << "success " << some_var << endl; ++some_var; }; throw 1; } catch(int){} { int some_var=1; cout << "Case #2: normal exit" << endl; scope(exit) { cout << "exit " << some_var << endl; ++some_var; }; scope(failure) { cout << "failure " << some_var << endl; ++some_var; }; scope(success) { cout << "success " << some_var << endl; ++some_var; }; }
在C ++ 98中是[noisier:]]
try { cout << "Case #1: stack unwinding" << endl; BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END throw 1; } catch(int){} { cout << "Case #2: normal exit" << endl; BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END }
此外,库具有UNWINDING_AWARE_DESTRUCTOR功能。 Example:
struct DestructorInClass { UNWINDING_AWARE_DESTRUCTOR(DestructorInClass,unwinding) { cout << "DestructorInClass, unwinding: " << ( unwinding ? "true" : "false" ) << endl; } };
但是,在某些情况下,UNWINDING_AWARE_DESTRUCTOR可能会give wrong results(尽管范围(成功)和范围(失败)功能不受此类问题的影响。