我的同事和我认为我们在Visual C ++ 2012和2013中发现了一个错误,但我们不确定。是否应该在以下代码中调用std :: current_exception返回非null exception_ptr?在我们尝试过的大多数其他编译器中似乎都是这样:
#include <exception>
#include <stdexcept>
#include <iostream>
class A
{
public:
~A()
{
try
{
throw std::runtime_error("oh no");
}
catch (std::exception &)
{
std::clog << (bool)std::current_exception() << std::endl;
}
}
};
void foo ()
{
A aa;
throw std::runtime_error("oh no");
}
int main(int argc, char **)
{
try
{
foo();
}
catch(...)
{
}
return 0;
}
在Visual C ++下运行时,我们得到“0”(false,表示返回的exception_ptr为null)。其他编译器,如g ++,打印“1”。
答案 0 :(得分:4)
cppreference说std::current_exception
:
如果在异常处理期间调用(通常在catch子句中),则捕获当前异常对象并创建一个std :: exception_ptr,它包含该异常对象的副本或引用(如果是副本,则为实现定义)是的。)
如果此函数的实现需要调用new并且调用失败,则返回的指针将保存对std :: bad_alloc
实例的引用如果此函数的实现需要复制捕获的异常对象并且其复制构造函数抛出异常,则返回的指针将保存对抛出的异常的引用。如果抛出的异常对象的拷贝构造函数也抛出,则返回的指针可以保存对std :: bad_exception实例的引用,以打破无限循环。
如果在没有处理异常时调用该函数,则返回空的std :: exception_ptr。
抛出异常展开你的堆栈,它应该在A
实例上调用aa
类的析构函数,在这个实例中你有一个简单的try/throw/catch
代码块来捕获异常。
当然它并不像标准那样具有权威性,但在我看来,g ++ / clang是正确的而视觉不是(反过来发生的次数较少:p)
答案 1 :(得分:3)
作为confirmed by James McNellis,这绝对是一个错误。今天我很高兴发现它。它仍未在Visual Studio 2015.1中修复。
在您的情况下,解决方法是在您的处理程序中调用make_exception_ptr
而不是current_exception
:
~A()
{
try
{
throw std::runtime_error("oh no");
}
catch (std::exception & e)
{
std::clog << (bool)std::make_exception_ptr(e) << std::endl;
}
}
但我认为我们对catch(...)
条款运气不佳,确实需要修复。
编辑1:很久以前我在连接中报告了它。它现在可以在Developper Community
上找到编辑2:在VS 2017 15.9中仍未修复。