На время жизни исключения влияют вложенные обработчики? - PullRequest
3 голосов
/ 21 декабря 2011

Рассмотрим следующий фрагмент кода:

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. временно сохраняется до тех пор, пока выполняется обработчик для это исключение. В частности, если обработчик завершает работу, выполняя бросить; оператор, который передает управление другому обработчику для того же исключение, поэтому временное остается. Когда последний обработчик исполняется за исключением выходов любым способом, кроме броска; временный объект уничтожен и реализация может быть освобождена память для временного объекта; любое такое освобождение делается в неуказанный способ. Разрушение происходит сразу после уничтожение объекта, заявленного в декларации-исключении в обработчик.

Правильно ли я рассматриваю обработчик в main как "последний обработчик?" И поэтому в HandleException разрешено любое количество повторных бросков и ловушек без разрушения текущего объекта исключения?

Ответы [ 2 ]

0 голосов
/ 14 января 2012

Спасибо за комментарии и ответы, опубликованные до сих пор.Я не совсем понял, что я ищу, поэтому я собираюсь добавить некоторую информацию из ответа, предоставленного aschepler , к моему последующему вопросу.

15,3p7: обработчик считается активным, когда инициализация завершена для формального параметра (если есть) предложения catch.... Обработчик больше не считается активным при выходе из оператора catch или при выходе из std :: непредвиденным () после его ввода из-за броска.

15.3p8: исключение для последнего активированного обработчика, которыйвсе еще активен, называется обработанным в настоящее время исключением.

Я думаю, что язык стандарта здесь вполне понятен и что main на самом деле является обработчиком last .Поэтому время жизни исключения не зависит от вложенных обработчиков.

0 голосов
/ 27 декабря 2011

Правильно ли я рассматриваю обработчик в main как «последний обработчик?»

Да, вы.

И поэтому в HandleException разрешено любое количество повторных бросков и ловушек без разрушения объекта текущего исключения?

Да. Объект исключения, который окончательно не обработан, будет уничтожен сгенерированным компилятором кодом. Никаких утечек памяти не будет.

Не стоит перебрасывать HandleException(). Вместо 1. записывать уловы в любой тип исключения, который запрашивает определенную обработку 2. вы можете сгруппировать обработку исключений, используя dynamic_cast. Поймайте базовый тип исключения и попытайтесь уменьшить его до любого из его производных классов исключений. НО dynamic_cast не является хорошей практикой. Так что лучше использовать 1-е решение.

Лучше переписать ваш код следующим образом:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...