2013-03-19 2 views
1

В: Безопасно ли бросить и поймать исключение в стеке, или приложение вызывает terminate во втором броске?Безопасно ли бросать/ловить на стеке?

минимальный пример:

void some_function() 
{ 
    try 
    { 
     // do stuff here that can throw 
     throw std::runtime_error("blah"); 
    } catch(const std::exception& re) 
    { 
     try // this code could be in some function called from here 
     { 
      // do something with re here that throws a logical_error 
      throw std::logical_error("blah blah"); // does this call terminate? 
     } catch(const std::logical_error& le) 
     { 
     } 
    } 
} 

Я получил любопытный после прочтения this question.

Примечание: Я знаю, что вы можете/должны catch(...) в разрушителя, но это имеет смысл вообще иметь в catch блоке с try/catch - может быть, в какой-то функции, называемой на исключение (re в моем примере)?

+2

На самом деле это не во время штабелирования, хотя, верно? AFAIK, как только будет введен блок catch, стек уже размотан. – Pubby

+1

Ahh ... thanks :) Если вы добавите его в качестве ответа, я его приму. – utnapistim

+0

Не нужно закрывать, я могу ошибаться. Мой комментарий был скорее предположением. – Pubby

ответ

4

На самом деле это не во время разматывания штабеля. После ввода блока catch блок уже разматывается.

И да, этот код является законным. См. Этот вопрос: Nested try...catch inside C++ exception handler?

+1

И наоборот, бросание деструктора ** может ** быть «на стеке». И для этого сценария есть четко определенное поведение. –

+1

+1. Да, когда он входит в блок 'catch', в полете нет никаких исключений, что означает, что блок' catch' может бросить; поведение хорошо определено. На самом деле, ретрол (который разрешен только с 'catch') - это один вид броска. – Nawaz

2

Ответ Pubby наилучшим образом соответствует сценарию, который вы описываете.

В качестве дополнения, в то время как стек разматывается, единственным исполняемым кодом пользователя является деструкторы (и код, который вызовут эти деструкторы).

Если вы сделать в деструктореthrow при этом сценарии, стандарт определяет, что std::terminate() будет называться.

+1

Не совсем. Если вы выбросите исключение **, которое распространяется из деструктора ** в этом сценарии, стандарт указывает, что будет вызван 'std :: terminate()'. 'try {throw 3; } catch (int) {} 'внутри деструктора не приведет к' std :: terminate() '. –