LINUX.ORG.RU

История изменений

Исправление 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, нет смысла требовать более сложной реализации от компилятора.