Действительно ли перебросок является исключением, законным во вложенной 'попытке'?

Действительно ли следующее четко определено в 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;
}

Я надеюсь, что образец показывает мое намерение. Мое предположение - то, что это - неопределенное поведение, но я не уверен. Обеспечьте кавычки из стандарта, если применимо. Альтернативные подходы ценятся также.

Спасибо!

22
задан Alexander Gessler 17 March 2010 в 21:43
поделиться

2 ответа

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

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

То есть:

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

    /* ... */

} // <--

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

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

12
ответ дан 29 November 2019 в 05:48
поделиться

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

3
ответ дан 29 November 2019 в 05:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: