Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

MinGW - SEH и SJLJ. Странное поведение

#cpp #исключения


Имеется в наличии невероятно простой код:

#include 

class C {
    public :
        C() try {
            throw std::runtime_error("C::C");
        } 
        catch (...) { }
};

int main() {
    C c;
}


Компилируем этот код компилятором MinGW-builds 8.1.0 x86_64 SJLJ и, запустив полученное
приложение, получаем следующий вывод:

terminate called after throwing an instance of 'std::runtime_error'
  what():  C::C

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.


А теперь сделаем то же самое, заменив компилятор на MinGW-builds 8.1.0 x86_64 SEH.
С удивлением наблюдаем, что строка с сообщением о типе исключения исчезла:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.


Собственно, вопрос. Почему? Что происходит? Так и должно быть или я чего-то не понимаю?

P.S. Интересно, что если у конструктора убрать function-try-block, т.е. привести
его к виду

C() {
    throw std::runtime_error("C::C");
}


то вывод при обоих способах обработки исключений идентичный.



ДОПОЛНЕНИЕ

Если добавить конструктору спецификатор noexcept, то поведение вновь становится одинаковым:

C() noexcept try {
    throw std::runtime_error("C::C");
}
catch (...) { }

    


Ответы

Ответ 1



Формально говоря, у вас в коде нет "обработки" исключений. Исключение, пойманное function-try-block конструктора, невозможно "подавить" - оно все равно будет перевыброшено автоматически, если вы этого не сделаете сами. То есть в любом из ваших вариантов исключение остается необработанным. Если исключение не обработано, то вызывается std::terminate, которая вызовет текущий обработчик terminate (terminate handler). А что делает установленный по умолчанию обработчик terminate - определяется реализацией. Вот эти различия между реализациями вы и наблюдаете. Например, если в GCC при помощи std::set_terminate задать свой пустой обработчик terminate, то вывод о типе исключения и вывод what() исчезнет.

Комментариев нет:

Отправить комментарий