受其他异常影响的异常的生命周期
Is the lifetime of an exception affected by other exceptions?
作为我上一个问题的后续:
如果我像这样修改代码:
struct ExceptionBase : virtual std::exception{};
struct SomeSpecificError : virtual ExceptionBase{};
struct SomeOtherError : virtual ExceptionBase{};
void MightThrow();
void HandleException();
void ReportError();
int main()
{
try
{
MightThrow();
}
catch( ... )
{
HandleException();
}
}
void MightThrow()
{
throw SomeSpecificError();
}
void HandleException()
{
try
{
throw;
}
catch( ExceptionBase const & )
{
// common error processing
}
try
{
throw;
}
catch( SomeSpecificError const & )
{
// specific error processing
}
catch( SomeOtherError const & )
{
// other error processing
}
try
{
ReportError();
}
catch( ... )
{
}
}
void ReportError()
{
throw SomeOtherError();
}
原始异常的"最后一个处理程序"(即main
中的一个)在第二个异常被抛出时没有退出,所以两个异常都是活动的吗?一旦我们离开第二个异常的处理程序,原始异常是否仍然可用?
c++ 11 (N3242):
15.1p4:异常对象的内存以未指定的方式分配,除非在3.7.4.1中指出。如果一个处理程序通过重新抛出退出,将控制传递给同一异常的另一个处理程序。一个例外对象的最后剩余活动处理程序以任何其他方式退出后,将销毁该异常而不是重新抛出,或者引用异常对象的类型
std::exception_ptr
(18.8.5)的最后一个对象销毁,以较晚者为准。
(std::exception_ptr
是c++ 11的特性,并没有在您的示例代码中使用)
15.3p7:当catch子句. ...的形式参数(如果有的话)初始化完成时,处理程序被认为是活动的一个处理程序当catch子句退出或当
std::unexpected()
在被由于投掷而进入。15.3p8:最近激活的处理程序仍然活动的异常称为当前处理的异常。
15.1p8:没有操作数的throw-expression会重新抛出当前处理的异常(15.3)。
或者等价地,我认为,throw;
总是指当前正在执行的最内层catch块捕获的异常。只是我没有像标准中定义的那样仔细地定义'最内部'和'执行'。
是的,一次可以分配多个异常对象,并且要求c++确保它们存在足够长的时间,以便在尝试重新抛出时做"正确的事情"。
不确定它有多标准,但如果我在HandleException
的末尾添加throw;
并用g++编译,结果程序告诉我:
root@xxxx [~/code]# ./a.out
terminate called after throwing an instance of 'SomeSpecificError'
what(): 17SomeSpecificError
Aborted
注意异常类型。这是MightThrow
抛出的异常,而不是ReportError
抛出的异常。
VS2010报告一个SomeSpecificError
一次只有一个"活动异常"。当您在异常处理程序中throw
另一个异常时,实际上您正在更改正在堆栈中传播的异常的类型。
关于标准参考…ISO/IEC 14882:2003,第15.3节[除。句柄],第8段为:
异常在进入处理程序时被认为已处理。(注意:堆栈将在那时展开。)
另一种说法是,一旦进入catch
块,原始异常就不再活动。
同样,一旦进入catch
块,uncaught_exception()
函数将返回false
。第15.5.3节[除非。未捕获)写道:
功能(更新2)
bool uncaught_exception() throw()
在完成要抛出的对象的计算后返回true,直到完成在匹配处理程序中初始化异常声明(18.6.4)。这包括堆栈展开。如果异常被重新抛出(15.1), uncaught_exception()从重新抛出点返回true直到重新抛出的异常再次被捕获。
同样相关的是第15.3节第4段:
所抛出异常的临时副本的内存为以未指定的方式分配,除非在3.7.3.1中指出。的只要有正在执行的处理程序,临时就会持续存在这个例外。特别地,如果处理程序通过执行
throw;
语句,该语句将控制传递给另一个处理程序异常,因此临时保留。当最后一个处理程序通过throw;
之外的任何方式为异常退出执行临时对象被销毁,实现可能会释放临时对象的内存;任何这样的重新分配都是在一种未指明的方式。破坏立即发生在类的异常声明中声明的对象的销毁处理程序。
因此,一旦通过裸throw;
以外的任何方式退出处理程序,原始异常就会被销毁。因此,如果您throw
其他异常,则退出处理程序并销毁原始异常。
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 函数如何通知用户它基于函数原型抛出异常?
- C++中抛出异常的生命周期
- 受其他异常影响的异常的生命周期
- 受嵌套处理程序影响的异常的生命周期