Как среда выполнения GCC (libstdc ++) решает завершить работу (), когда исключение активно - PullRequest
2 голосов
/ 08 октября 2019

Мы знаем, что terminate () вызывается, если в настоящее время активно исключение, и есть другой вызов throw.

Хотите понять, чем это отличается от ситуации, когда *Блок 1005 * делает throw из-в? Я предполагаю, что если выполняется блок catch, это означает активное исключение.

class exception_type{}

try{ ... throw obj; ... 
}catch(exception_type& obj){
 ...
 ... 
 throw x;
 ...
}

Из этого примера кода, поскольку у нас есть еще один throw здесь в блоке catch, которыйдолжен быть пойман другим обработчиком в динамически включенном блоке try. Так что это похоже на правильное использование throw внутри catch. Но на данный момент у нас уже есть активное исключение. Почему это не должно вызывать terminate () для вызова? Или, другими словами, как именно среда выполнения c ++ gcc распознает, что уже существует активное исключение и необходимо вызвать terminate ().

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Благодарность за этот ответ принадлежит @HolyBlackCat, который намекнул на это в своем ответе.

Ответ throw - это сложный процесс, в котором C ++ во время выполнения должен выполнить несколько различных действий. Хотя фактический процесс может быть определен реализацией во время выполнения, но мало что может быть понято совместно. Эта бумага может пролить немного света. См. Раздел 3.3.

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

Наконец, когда введен подходящий catch, активное исключение уничтожается, и он начинает выполнять код обработчика. По этой причине throw, как показано в вопросе, не будет испытывать никаких активных исключений.

Это также объясняет, почему мы не должны throw исключение из деструктора, который выходит из области видимости. На самом деле было бы неплохо иметь блок try{....}catch(...) в деструкторе для защиты от любых нежелательных terminate () инцидентов.

1 голос
/ 08 октября 2019

Исключение перестает быть «активным», как только оно catch ed (когда управление входит в секцию catch).

...