Будет ли C ++ генерировать без аргументов работать внутри другого фрейма, чтобы перебросить исключение? - PullRequest
5 голосов
/ 25 августа 2010

Если у меня есть код, подобный следующему:

try {
  doSomething();
} catch (...) {
  noteError();
}

void noteError() {
  try {
    throw;
  } catch (std::exception &err) {
    std::cerr << "Note known error here: " << err.what();
  } catch (...) {
    std::cerr << "Note unknown error here.";
  }
  throw;
}

Будут ли исходные исключения выбрасываться из обоих мест внутри нижней рамки noteError ()?

Ответы [ 2 ]

6 голосов
/ 25 августа 2010

Ваш оригинальный код был в порядке. Вы перехватили разные типы исключений и вызвали функцию, которая будет регистрировать сообщения и повторно отправлять их. Оператор throw не обязательно должен отображаться непосредственно внутри соответствующего блока catch. Если вы вызываете одну из этих функций «заметки» и вы не в настоящее время обрабатываете исключение, то ваша программа будет вызывать terminate().

Ваш новый код тоже в порядке. Можно все перехватить, а затем вызвать другую функцию, которая перебрасывается, чтобы перейти к более конкретному обработчику. Это диспетчер исключений , описанный в FAQ C ++ . Выглядит немного странным, чтобы перебросить исключение после , когда блок диспетчеризации завершился, но если тот же оператор throw произошел после того, как noteError вернул (внутри исходного блока catch) вместо того, где сейчас, тогда это было бы совершенно обыденно; это продемонстрировано в стандарте, §15.1 / 6.

4 голосов
/ 25 августа 2010

Формулировка в стандарте (§15.1 / 2) (выделено мной):

При возникновении исключения управление передается ближайшему обработчику с соответствующим типом (15.3); «Ближайший» означает обработчик, для которого составной оператор, инициализатор ctor или тело функции после ключевого слова try был недавно введен потоком управления и еще не завершен.

Когда блок try "вышел"? Согласно грамматике (§15 / 1) блоки try заканчиваются последовательностью обработчиков , поэтому блок заканчивается, когда заканчивается последний обработчик. Другими словами:

try // <- start of try block
{
}
catch (whatever) // <- first handler
{
}
// ... more handlers
catch (whatever_again) // <- last handler
{
} // <- end of try block

Так что да, ваш код в порядке. При повторном отбрасывании ближайший блок try имеет соответствующий обработчик (а именно catch (...)), поэтому этот обработчик вводится.

...