Допустимо ли повторное создание исключения во вложенной попытке? - PullRequest
22 голосов
/ 18 марта 2010

Хорошо ли определено следующее в 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 ]

12 голосов
/ 18 марта 2010

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

§15.1 / 4: Память для временной копии создаваемого исключения распределяется неопределенным образом, за исключением случаев, указанных в 3.7.4.1. Временное состояние сохраняется до тех пор, пока для этого исключения выполняется обработчик.

То есть:

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

    /* ... */

} // <--

Между этими стрелками вы можете повторно выдать исключение. Только когда заканчивается область действия обработчиков, исключение перестает существовать.

Имейте в виду, что если вы позвоните dispatch без активного исключения, будет вызван terminate. Если dispatch выдает исключение в одном, если это обработчики, , то исключение начнет распространяться. Больше информации в связанном вопросе .

2 голосов
/ 18 марта 2010

Так как dispatcher, вызванный в блоке catch, throw вызовет исключение.Если вы будете звонить dispatcher вне блока перехвата, будет вызван terminate() (согласно 15.1 / 8).В любом случае не существует неопределенного поведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...