Подтвердить что ты не робот

Отсутствует деструктор в Visual Studio?

Я написал следующую программу:

// Example program
#include <iostream>
#include <string>
#include <exception>

struct A {
    A() {
        std::cout << "A ctor" << std::endl;

    }

    ~A() { 
        std::cout << "A dtor" << std::endl;
        try {
            throw std::exception();
        } catch (std::exception &e) {
            std::cout << "Internal exception caught" << std::endl;
        }
    }
};

int main()
{
    try {
        A a;
        throw std::exception();
    } catch (std::exception &e) {
        std::cout << "External exception caught" << std::endl;
    }
}

Ожидаемый результат:

A ctor
A dtor
Internal exception caught
External exception caught

И это то, что я получаю в GCC. Но когда я использую Visual Studio (версия 2013), вывод, который я получаю, это:

A ctor
External exception caught

Что здесь происходит?

4b9b3361

Ответ 1

MSVC2013 здесь неправильный, и GCC прав. К сожалению, сейчас я не могу найти подходящую ссылку из стандарта, но согласно std:: uncaught_exception:

Например, если разворачивание стека приводит к тому, что объект, выделенный в стеке, будет destructed, деструктор для этого объекта может запускать код, который бросает исключение, если исключение поймано некоторым блоком catch перед тем как выйти из деструктора.

Подробнее см. также раздел "Отбрасывание во время размотки стека" здесь.

Наконец, как упоминается @StoryTeller, это поведение не воспроизводится с новыми версиями MSVC.


Самое близкое совпадение в стандарте, которое я могу найти, следующий (из проекта N3936):

15.1 Бросок исключения [except.throw]

  1. Если механизм обработки исключений, после завершения инициализация объекта исключения, но до активации обработчик для исключения, вызывает функцию, которая выходит через исключение, вызывается std:: terminate.

Итак, формально, вполне нормально вызывать функцию во время процесса разворачивания стека (включая деструктор), который может иметь дело с исключением, но если исключение внутри такой функции не улавливается соответствующим блоком catch, тогда std::terminate должно называться.