LINUX.ORG.RU

Файловые потоки и причины ошибок

 


1

2

Задумался я тут над элементарным вопросом о C++:

Как грамотно различать ошибки при работе с файловыми потоками (std::ofstream)?

Справочник по стандартной библиотеке указывает только на наличие флагов failbit, badbit, eofbit и соотв. геттеры. Гугл выдает какие-то мутные рецепты с SO, в которых при возникновении ошибок при работе с std::ofstream/ifstream подразумевается, что errno будет содержать код ошибки, как для операций В/В в стандартной библиотеке C.

Но с какой стати, если стандартная библиотека С++ не обязана ничего знать о существовании errno? По крайней мере в драфте стандарта C++11 в разделе о стандартной библиотеке ничего не сказано о errno.

★★★★★

Но с какой стати, если стандартная библиотека С++ не обязана ничего знать о существовании errno?

С чего бы? В стандартную библиотеку C++ входит и стандартная библиотека C. Для удобства их ещё и в std:: запихали, и C++-хедеры приделали: https://en.cppreference.com/w/cpp/header/cerrno

XMs ★★★★★
()

Возможно, что в тексте исключений что-то будет, только их надо включить. А с C++11 std::ios_base::failure наследуется от system_error, там может быть больше информации.

xaizek ★★★★★
()

Как грамотно различать ошибки при работе с файловыми потоками (std::ofstream)?

Ловить std::ios_base::failure.

27.5.3.3.1 параграф 2:

When throwing ios_base::failure exceptions, implementations should provide values of ec that identify the specific reason for the failure. [ Note: Errors arising from the operating system would typically be reported as system_category() errors with an error value of the error number reported by the operating system. Errors arising from within the stream library would typically be reported as error_code(io_errc::stream, iostream_category()). — end note ]

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)

По стандарту не обязана.

Но существующие реализации вызывают код libc, поэтому errno выставляется, если ошибка происходит в libc.

Ivan_qrt ★★★★★
()

можно не выпендриваться и юзать сишные функции

Harald ★★★★★
()
Ответ на: комментарий от intelfx

Это да, я указывал на некорректность конкретного суждения

XMs ★★★★★
()
Ответ на: комментарий от intelfx

27.5.3.3.1 параграф 2:

Ты наверное имел ввиду 27.5.3.1.1 Class ios_base::failure.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от intelfx

Причем, ни gcc ни clang «does not provide». На сколько я понял, boost::filesystem::ofstream тоже ничего в плане ошибок не дает по сравнению с std::basic_ofstream, чисто обертка для интеграции с boost::filesystem::path.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

boost::filesystem::ofstream тоже ничего в плане ошибок не дает

Подтверждаю: не дает. Специально проверил.
Возможно Boost Iostreams умеет определять ошибки, но я не пробовал. Так или иначе, пожалуй проще и быстрее использовать (хоть это и не по c++-ному):

cerr << strerror(errno) << endl;

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

Публичные функции boost::filesystem заполняют boost::error_code, в котором содержится код ошибки от операционки (на Windows достается из ::GetLastError, на POSIX errno). Перегрузки не выбрасывающие исключения пишут его в параметр, переданный по ссылке. Перегрузки выбрасывающие исключения вкладывают его в само исключение.

А вот boost::filesystem::fstream действительно простейшая обертка над std::fstream. Тут уже подробности (от ОС) о том, что за ошибка произошла клиентскому коду явно не транслируют.

dvetutnev ★
()

failure содержит errno если это произошло на операции чтения
во всех остальных случаях оно не нужно

anonymous
()
Ответ на: комментарий от seiken

вы слишком хотите от иострим потоков
для того что вы говорите сделали std:filesystem
как помню в комитете обсуждали вообще оистрим сделать депрекейтед и удалить

anonymous
()
Ответ на: комментарий от anonymous

кстати да, посмотрел, оно платформик специфик оказалось
но в целом за десятки лет использования для вывода и ввода с файлов
не припомню что бы в errno была необходимость

anonymous
()
Ответ на: комментарий от anonymous

Разве это много? Особенно учитывая то, что в errno это давно имеется.

rumgot ★★★★★
()
Ответ на: комментарий от anonymous

Ты не понял видимо. Действующий это какой? 11, 14, 17 ? Они все действующие. Правильнее выражаться «последний» :-)

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

А как отозванное может действовать?

anonymous
()
Ответ на: комментарий от anonymous

Гугл переводит это слово «Изъятый». Госприемка - это не самый лучший показатель.

rumgot ★★★★★
()
Ответ на: комментарий от seiken

Как это в 'остальных не нужно'? А файл не найден, недостаточно прав и др.?

Для логики приложения не часто нужно. А вот лог конкретную ошибку записать было бы полезно. Вариант при неудачи ручками выдернуть из errno/::GetLastError. Но это не очень надежно, нет гарантии, что в этом же треде потом не было обращения к API операцинки. Implementation defined получается.

dvetutnev ★
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.