Блок C ++ try / catch не перехватывает исключение указанного типа - PullRequest
3 голосов
/ 25 сентября 2019

Я только что столкнулся со случаем, когда исключение типа std::ios_base::failure было сгенерировано внутри блока try, который перехватывает исключение этого типа, но оно не перехватывается.

Минимальный рабочий пример

#include <fstream>
#include <iostream>

int main()
{
    std::ofstream file;
    file.exceptions( std::ofstream::failbit );
    try {
        file.open( "no_write_access" );
    } catch ( const std::ios_base::failure& e ) {
        std::cout << "Look, Ma, I caught an error!" << std::endl;
    }
}

Компиляция и выполнение

 % g++ --version
g++ (GCC) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

 % g++ main.cpp -std=c++11 -o test && ./test
terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear
[1]    9734 abort      ./test

Обсуждение

Что здесь происходит?В сообщении «прекратить» явно указывается, что тип исключения был std::ios_base::failure, поэтому я не вижу причин, по которым его не поймают.

Интересно, что блок catch работает , если я ловлю const std::exception&, но не работает, если я ловлю const std::runtime_error& (который в C ++ 11 является базовым классом std::ios_base::failure,согласно cppreference ).

EDIT : Я только что попробовал g++ 9.2.0, и он работает правильно.Я пробовал несколько разных версий, и поведение менялось иногда между 6.3.0 и 7.2.0.Мне все еще любопытно, знает ли кто-нибудь причину, но похоже, что это может быть связано с ошибкой в ​​gcc.

...