是否在嵌套的“尝试”中重新抛出异常合法?

时间:2010-03-17 21:43:59

标签: c++ exception-handling

以下是否在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;
}

我希望样本显示我的意图。我的猜测是这是未定义的行为,但我不确定。如果适用,请提供标准的报价。另外的方法也很受欢迎。

谢谢!

2 个答案:

答案 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)。在任何情况下都没有未定义的行为。