Я только что столкнулся со случаем, когда исключение типа 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
.