代码之家  ›  专栏  ›  技术社区  ›  Alexander Gessler

在嵌套的“try”中重新引发异常是否合法?

  •  22
  • Alexander Gessler  · 技术社区  · 14 年前

    下面是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 回复  |  直到 14 年前
        1
  •  12
  •   Community c0D3l0g1c    7 年前

    没关系。异常在捕获之前一直处于活动状态,此时它变为非活动状态。但是 它一直存在到处理程序的作用域结束。 从标准来看,重点是我的:

    第15章第4节: 正在引发的异常的临时副本的内存以未指定的方式分配,但3.7.4.1中所述的情况除外。 只要对该异常执行了处理程序,临时的就将持续存在。

    即:

    catch(...)
    { // <--
    
        /* ... */
    
    } // <--
    

    在这些箭头之间,可以重新抛出异常。只有当处理程序作用域结束时,异常才会停止存在。

    如果你打电话给 dispatch 没有异常, terminate 将被调用。如果 派遣 如果是处理程序,则在其中引发异常, 那个 异常将开始传播。更多信息 a related question .

        2
  •  2
  •   Kirill V. Lyadvinsky    14 年前

    自从 dispatcher 在catch块中调用 throw 将重新引发异常。如果你打电话来 调度员 然后在外面挡块 terminate() 将被调用(根据15.1/8)。在任何情况下都没有未定义的行为。