我可以在堆栈展开期间使用std :: current_exception吗? [英] Can I use std::current_exception during stack unwinding?

查看:390
本文介绍了我可以在堆栈展开期间使用std :: current_exception吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在堆栈展开期间销毁的对象的析构函数中使用std :: current_exception?



关于cppreference的文档说:


在异常处理期间调用(通常在catch子句中)捕获当前异常对象(...)


但不清楚对于我来说,堆栈展开是否是异常处理的一部分。



在某些最高



我对我的编译器做了一些测试(g ++(Ubuntu 4.8.2-19ubuntu1)4.8.2) ),似乎在这种情况下,std :: current_exception返回空指针。

  #include< exception> 
#include< stdexcept>
#include< iostream>


struct A
{
〜A()
{
std :: clog< in destructor<< std :: endl;
std :: clog<< uncaught_exception:< std :: uncaught_exception()<< std :: endl;
std :: clog<< current_exception:<< (bool)std :: current_exception()< std :: endl;
}
};

int main(int argc,char **)
{
try
{
A aa;
std :: clog<< before throw<<< std :: endl;
if(argc> 1)
throw std :: runtime_error(哦no);
}
catch(...)
{
std :: clog<< in catch block<<< std :: endl;
std :: clog<< uncaught_exception:< std :: uncaught_exception()<< std :: endl;
std :: clog<< current_exception:< (bool)std :: current_exception()< std :: endl;
}

return 0;
}

输出为:

  before throw 
在析构函数中
uncaught_exception:1
current_exception:0
在catch块中
uncaught_exception:0
current_exception:1

有人知道标准的含义吗?

解决方案

C ++标准定义 current_exception() in section§18.8.5 [propagation]:



(强调我)


exception_ptr current_exception()noexcept;



:一个exception_ptr对象,它引用当前处理的
异常(15.3)或当前处理的异常的副本,或者如果没有异常处理,则为
null exception_ptr对象。
引用对象应至少保持有效,只要有引用它的
exception_ptr对象。


and§15.3 [except.handle],note 7 and 8:



  1. 当catch子句的
    参数(如果有)的初始化完成时,处理程序被视为活动。 [注意:堆叠将在此时释放
    。 - end note]


  2. 最近激活的处理程序仍为
    活动
    的异常称为

  3. href =http://en.cppreference.com/w/cpp/error/current_exception> current_exception() 定义为当前处理的异常,这是最近的活动处理程序的例外,并且处理程序仅在堆栈展开完成时有效。






    如你的测试所示,在堆栈展开期间没有活动处理程序,因此没有当前处理的异常:在这种情况下, current_exception() 将返回null exception_ptr


    Should it be possible to use std::current_exception inside destructors of objects that are destroyed during stack unwinding?

    Documentation on cppreference says:

    If called during exception handling (typically, in a catch clause), captures the current exception object (...)

    But it's not clear for me whether stack unwinding is a part of exception handling.

    In some highest-ranked answer on stackoverflow author assumes that it's possible.

    I did some test on my compiler (g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2) and it seems, that std::current_exception returns empty pointer in this case.

    #include <exception>
    #include <stdexcept>
    #include <iostream>
    
    
    struct A
    {
        ~A()
        {
            std::clog << "in destructor"<<std::endl;
            std::clog << "uncaught_exception: " << std::uncaught_exception() << std::endl;
            std::clog << "current_exception: " << (bool)std::current_exception() << std::endl;
        }
    };
    
    int main(int argc, char **)
    {
        try
        {
            A aa;
            std::clog << "before throw"<<std::endl;
            if(argc>1)
                throw std::runtime_error("oh no");
        }
        catch(...)
        {
            std::clog << "in catch block"<<std::endl;
            std::clog << "uncaught_exception: " << std::uncaught_exception() << std::endl;
            std::clog << "current_exception: " << (bool)std::current_exception() << std::endl;
        }
    
        return 0;
    }
    

    The output is:

    before throw
    in destructor
    uncaught_exception: 1
    current_exception: 0
    in catch block
    uncaught_exception: 0
    current_exception: 1
    

    Does anybody know what the standard says?

    解决方案

    C++ Standard defines current_exception() in section § 18.8.5 [propagation] :

    (emphasis mine)

    exception_ptr current_exception() noexcept;

    Returns: An exception_ptr object that refers to the currently handled exception (15.3) or a copy of the currently handled exception, or a null exception_ptr object if no exception is being handled. The referenced object shall remain valid at least as long as there is an exception_ptr object that refers to it.

    And § 15.3 [except.handle], notes 7 and 8 :

    1. A handler is considered active when initialization is complete for the parameter (if any) of the catch clause. [ Note: The stack will have been unwound at that point. — end note ]

    2. The exception with the most recently activated handler that is still active is called the currently handled exception.

    The exception returned by current_exception() is defined as the "currently handled exception", which is the exception of the most recent active handler, and a handler is active only when stack unwinding completed.


    As your tests have shown, there is no "active handler" during stack unwinding, so there is no "currently handled exception" either : in that case, current_exception() will return a null exception_ptr.

    这篇关于我可以在堆栈展开期间使用std :: current_exception吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆