История изменений
Исправление
gv,
(текущая версия)
:
Думаю, так:
- Для любой области генерируется код раскрутки стека, который вызывает деструкторы всех объектов, которые были созданы в этой области до возникновения исключения.
В области видимости ~Test() такие объекты - это A, B, Base. Компилятор генерирует одинаковый код для любых областей, в том числе для деструктора.
- terminate() вызывается в двух случаях: а) если исключение вышло за main() и б) если исключение генерируется во время раскрутки стека (в gcc это видимо проверяет __cxa_throw).
Больше никаких проверок компилятор не вставляет (для простоты реализации). Когда исключение генерируется в ~Test(), ни одно из двух условий не выполнено.
- Когда в деструкторе было сгенерировано исключение, выполнялась реализация delete, которая выглядит примерно так:
test->~Test(); test->operator delete();
Первая строка сгенерировала исключение. Вторая строка не выполнилась, вместо этого началась стандартная раскрутка стека. Для компилятора никаких частных случаев здесь нет.
Можно было бы требовать от компилятора такой реализации:
try { test->~Test(); } catch (...) { test->operator delete(); throw; } test->operator delete();
Однако в обоих случаях результат - UB. Если в результате все равно UB, нет смысла требовать более сложной реализации от компилятора.
Исходная версия
gv,
:
Думаю, так:
- Для любой области генерируется код раскрутки стека, который вызывает деструкторы всех объектов, которые были созданы в этой области до возникновения исключения.
В области видимости ~Test() такие объекты - это A, B, Base. Компилятор генерирует одинаковый код для любых областей, в том числе для деструктора.
- terminate() вызывается в двух случаях: а) если исключение вышло за main() и б) если исключение генерируется во время раскрутки стека (в это видимо проверяет __cxa_throw).
Больше никаких проверок компилятор не вставляет (для простоты реализации). Когда исключение генерируется в ~Test(), ни одно из двух условий не выполнено.
- Когда в деструкторе было сгенерировано исключение, выполнялась реализация delete, которая выглядит примерно так:
test->~Test(); test->operator delete();
Первая строка сгенерировала исключение. Вторая строка не выполнилась, вместо этого началась стандартная раскрутка стека. Для компилятора никаких частных случаев здесь нет.
Можно было бы требовать от компилятора такой реализации:
try { test->~Test(); } catch (...) { test->operator delete(); throw; } test->operator delete();
Однако в обоих случаях результат - UB. Если в результате все равно UB, нет смысла требовать более сложной реализации от компилятора.