Если в моем коде у меня есть следующий фрагмент:
try {
doSomething();
} catch (...) {
doSomethingElse();
throw;
}
Будет ли бросок повторно вызывать конкретное исключение, перехваченное обработчиком с многоточием по умолчанию?
Если в моем коде у меня есть следующий фрагмент:
try {
doSomething();
} catch (...) {
doSomethingElse();
throw;
}
Будет ли бросок повторно вызывать конкретное исключение, перехваченное обработчиком с многоточием по умолчанию?
да. Исключение активно до тех пор, пока оно не будет перехвачено, после чего оно становится неактивным. Но он живет до тех пор, пока область действия обработчика не закончится. Из стандарта, акцент мой:
§15.1/4: память для временной копии создаваемого исключения выделяется неуказанным образом, за исключением случаев, указанных в 3.7.4.1. Временное состояние сохраняется до тех пор, пока для этого исключения выполняется обработчик.
Это:
catch(...)
{ // <--
/* ... */
} // <--
Между этими стрелками вы можете повторно создать исключение. Только когда область обработчиков заканчивается, исключение перестает существовать.
Фактически, в §15.1/6 приведенный пример почти такой же, как ваш код:
try {
// ...
}
catch (...) { // catch all exceptions
// respond (partially) to exception <-- ! :D
throw; //pass the exception to some
// other handler
}
Имейте в виду, что если вы throw
не активируете исключение, будет вызвано terminate
. Это не может иметь место для вас, будучи в обработчике.
Если выдается doSomethingElse()
, а у исключения нет соответствующего обработчика, поскольку исходное исключение считается обработанным, новое исключение заменит его. (Как будто только что бросили, начинает раскручивать стопку и т.д.)
Это:
void doSomethingElse(void)
{
try
{
throw "this is fine";
}
catch(...)
{
// the previous exception dies, back to
// using the original exception
}
try
{
// rethrow the exception that was
// active when doSomethingElse was called
throw;
}
catch (...)
{
throw; // and let it go again
}
throw "this replaces the old exception";
// this new one takes over, begins stack unwinding
// leaves the catch's scope, old exception is done living,
// and now back to normal exception stuff
}
try
{
throw "original exception";
}
catch (...)
{
doSomethingElse();
throw; // this won't actually be reached,
// the new exception has begun propagating
}
Конечно, если ничего не выбрасывается, будет достигнуто throw;
, и вы сгенерируете пойманное исключение, как и ожидалось.
terminate
вызывается; см. последнюю строку примера, throw 2;
, где 2
— новое исключение.
- person Mike DeSimone; 19.03.2010
throw;
, временный объект уничтожается. В частности, выход с помощью throw
выражения-присваивания является другим. Вы думаете о выбросе из деструктора во время раскрутки до выполнения обработчика, и поведение для этого явно определено в 15.2/3.
- person Steve Jessop; 19.03.2010
catch
не вызывает terminate
или любого другого другое особое поведение. Согласно §15.3/8, исключение считается обработанным при входе в обработчик. Единственная особенность среды выполнения в блоке throw
заключается в том, что на объект исключения ссылается повторный бросок. (И особые случаи, которые применяются к конструкторам/деструкторам.)
- person Potatoswatter; 19.03.2010
doSomethingElse
выбрасывает (из деструктора, не меньше), но не вызывает терминter. По крайней мере, не в моей реализации и не в соответствии с моим прочтением стандарта.
- person Steve Jessop; 19.03.2010
throw "this replaces the old exception";
никогда не достигается, потому что функция заканчивается на throw; // and let it go again
.
- person Oktalist; 15.12.2014