std :: current_exception应该从类的析构函数中的catch块返回非null值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了std :: current_exception应该从类的析构函数中的catch块返回非null值相关的知识,希望对你有一定的参考价值。

我的同事和我认为我们在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”。

答案

cppreference说这关于std::current_exception

如果在异常处理期间调用(通常在catch子句中),则捕获当前异常对象并创建一个std :: exception_ptr,该std :: exception_ptr包含该异常对象的副本或引用(如果进行了复制,则为实现定义) 。

如果此函数的实现需要调用new并且调用失败,则返回的指针将保存对std :: bad_alloc实例的引用

如果此函数的实现需要复制捕获的异常对象并且其复制构造函数抛出异常,则返回的指针将保留对抛出的异常的引用。如果抛出的异常对象的拷贝构造函数也抛出,则返回的指针可以保存对std :: bad_exception实例的引用以打破无限循环。

如果在没有处理异常时调用该函数,则返回空的std :: exception_ptr。

抛出一个异常展开你的堆栈,它应该在你的A实例上调用aa类的析构函数,在这个实例中你有一个简单的try/throw/catch代码块来捕获异常。

当然它并不像标准那样具有权威性,但在我看来g ++ / clang是正确的而视觉不是(反过来发生的次数较少:p)

另一答案

作为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(...)条款运气不佳,确实需要修复。

Edit1:很久以前我在连接中报告了它。它现在可以在Developper Community上找到

编辑2:在VS 2017 15.9中仍未修复。

以上是关于std :: current_exception应该从类的析构函数中的catch块返回非null值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中将整个文件读入 std::string?

R 检查不喜欢 std:cout (C++)

无法捕获 std::runtime_error

围绕函数调用 std::thread() 的工作方式不同

使用 std::variant 的静态多态性

将std :: array变量作为参数传递