嵌套处理程序是否会影响异常的生命周期?

时间:2011-12-21 19:17:07

标签: c++ exception exception-handling

请考虑以下代码段:

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
  }

  ReportError();
}

void ReportError()
{
}

标准中的第15.1.4节告诉我们:

  

抛出异常的临时副本的内存是   除非在3.7.3.1中指出,否则以未指明的方式分配。该   只要有正在执行的处理程序,临时就会持久存在   那个例外。特别是,如果处理程序通过执行a退出   扔;语句,将控制传递给另一个处理程序   例外,所以临时遗体。 当最后一个处理程序出现时   通过除throw之外的任何方式执行异常退出;该   临时对象被销毁,实现可能会解除分配   临时对象的内存;任何这样的解除分配都是在   一种未说明的方式。破坏后立即发生破坏   破坏在异常声明中声明的对象   处理程序。

我是否正确地将main中的处理程序视为“最后一个处理程序?”因此HandleException中允许任何数量的重新抛出和捕获而不会导致当前异常对象的破坏?

2 个答案:

答案 0 :(得分:0)

我是否正确查看main中的处理程序作为“最后一个处理程序?”

是的,你是。

因此HandleException中允许任何数量的重新抛出和捕获而不会导致当前异常对象的破坏吗?

是。最终未处理的异常对象将被编译器生成的代码销毁。不会造成内存泄漏。

重新投入HandleException()并不好。代替 1.将catch捕获到任何请求特定处理的异常类型; 2.您可以使用dynamic_cast对异常处理进行分组。捕获基本异常类型并尝试将其向下转换为其任何派生异常类。但dynamic_cast不是好习惯。所以最好使用第一种解决方案。

最好以下列方式重写代码:

struct ExceptionBase : virtual std::exception{};
struct SomeSpecificError : virtual ExceptionBase{};
struct SomeOtherError : virtual ExceptionBase{};

void MightThrow();
void HandleExceptionBase();

int main()
{
  try
  {
    MightThrow();
  }
  catch (SomeOtherError &error) {
    // first common code
    HandleExceptionBase();
    // react on this exception correctly
    // specific code
  }
  catch (SomeSpecificError &error) {
    // first common code
    HandleExceptionBase();
    // react on this exception correctly
    // specific code
  }
  catch (ExceptionBase &error) {
    HandleExceptionBase();
    // finally catch anything derived from base class
    // react on this exception correctly
  }
  catch(...) {
    // react on any other exception except 3 listed above
  }
}

void MightThrow()
{
  throw SomeSpecificError();
}

void HandleExceptionBase() {
  // base exception handler
}

答案 1 :(得分:0)

感谢迄今为止发布的评论和答案。我还没有看到我正在寻找的内容,所以我要将an answer provided by aschepler中的一些信息添加到我的后续问题中。

  

15.3p7:当catch子句的形式参数(如果有)的初始化完成时,处理程序被认为是活动的。 ......一个处理程序   当catch子句退出或何时退出时,不再将其视为活动状态   std :: unexpected()由于抛出而在输入后退出。

     

15.3p8:最近激活的处理程序仍处于活动状态的异常称为当前处理的异常。

我认为标准的语言在这里非常清楚,main实际上是 last 处理程序。因此,异常的生命周期不受嵌套处理程序的影响。