Всегда ли stdio задает errno?

Когда поток stdio встречает ошибку (но не EOF), индикатор ошибки потока будет установлен таким образом, что ferror() будет возвращать ненулевое значение. Я всегда предполагал, что в errno имеется больше информации. Но откуда я это знаю?

Документация для некоторых функций [. man fopen под Linux] говорит, что errno также будет установлен. Однако man fgets вообще не упоминает errno. Информационные страницы glibc обнадеживают:

В дополнение к установке индикатора ошибки, связанного с поток, функции, которые работают с потоками, также устанавливают `errno 'в так же, как соответствующие низкоуровневые функции, которые работают с файлом дескрипторы.

Но я не знаю, насколько сильна эта гарантия. Требуется ли это по стандарту C? Что происходит в Visual C/С++?

Ответ 1

Сам стандарт C не требует особого использования функций errno WRT для stdio; он указывает ferror(), но говорит только об этом

7.13.10.3 Функция ferror Функция ferror проверяет индикатор ошибки для потока, на который указывает поток. Функция ferror возвращает ненулевое значение тогда и только тогда, когда для потока установлен индикатор ошибки.

из проекта C99: http://www.vmunix.com/~gabor/c/draft.html. Любые фактические коды ошибок используются, по большей части, для реализации.

Однако библиотека GNU C на linux также соответствует спецификациям POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm

которые в этом контексте более четко определены. Например, если вы посмотрите на страницу fopen:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html

В разделе "Ошибки" вы увидите много подробной информации, включая конкретные коды errno.

Опять же, библиотека GNU C, используемая практически во всех нормальных Linux-системах, совместима с POSIX, поэтому вы можете рассчитывать на эту информацию;). Те (онлайн) страницы руководства POSIX также, как правило, более подробные, чем стандартные страницы руководства системы Linux (читайте оба).

WRT для операций с файлами на других (не-POSIX) платформах, они будут иметь свои собственные реализации. К сожалению, такие вещи не прозрачно переносятся в стандартном C. В потоках С++ есть более стандартизованная обработка ошибок.

Ответ 2

В соответствии со стандартом C11, глава 7.21 ( "stdio.h" ), только fgetpos, fsetpos и ftell записываются в errno в случае ошибки.