以下是否在C ++中定义良好?我被迫将“转换”异常转换为返回代码(有问题的API被许多C用户使用,因此我需要确保在将控制权返回给调用者之前捕获并处理所有C ++异常。)
enum ErrorCode {…};
ErrorCode dispatcher() {
try {
throw;
}
catch (std::bad_alloc&) {
return ErrorCode_OutOfMemory;
}
catch (std::logic_error&) {
return ErrorCode_LogicError;
}
catch (myownstdexcderivedclass&) {
return ErrorCode_42;
}
catch(...) {
return ErrorCode_UnknownWeWillAllDie;
}
}
ErrorCode apifunc() {
try {
// foo() might throw anything
foo();
}
catch(...) {
// dispatcher rethrows the exception and does fine-grained handling
return dispatcher();
}
return ErrorCode_Fine;
}
ErrorCode apifunc2() {
try {
// bar() might throw anything
bar();
}
catch(...) {
return dispatcher();
}
return ErrorCode_Fine;
}
我希望样本显示我的意图。我的猜测是这是未定义的行为,但我不确定。如果适用,请提供标准的报价。另外的方法也很受欢迎。
谢谢!
答案 0 :(得分:12)
没关系。该异常处于活动状态,直到它被捕获,并且变为非活动状态。但是它一直存在,直到处理程序的范围结束。从标准,强调我的:
第15.1节/ 4: 抛出的异常临时副本的内存以未指定的方式分配,除非在3.7.4.1中说明。 只要存在为该异常执行的处理程序,临时就会持续存在。
那是:
catch(...)
{ // <--
/* ... */
} // <--
在这些箭头之间,您可以重新抛出异常。只有当处理程序范围结束时,异常才会消失。
请注意,如果您在没有活动例外的情况下致电dispatch
,则会调用terminate
。如果dispatch
在一个处理程序中抛出异常,那么该异常将开始传播。有关详情,请参见a related question。
答案 1 :(得分:2)
由于catch块dispatcher
中调用的throw
将重新抛出异常。如果您将在catch区块外调用dispatcher
,则将调用terminate()
(根据15.1 / 8)。在任何情况下都没有未定义的行为。