Что должна возвращать функция printf() в случае ошибки?

Читаю ман по printf(): "В случае успеха, возвращается количество напечатанных байт. В случае ошибки возвращается отрицательное значение.".

Ок, хорошо. Есть такой код:

#include <stdio.h>
#include <unistd.h>


int main( int argc, char* argv[], char* envp[] ){
    
    int res;
    
    close( 1 );
    
    res = printf( "0_0\n" );
    perror( "printf" );
    dprintf( 2, "code is %i\n", res );
    
    return 0;
}

В коде я закрываю stdout и вызываю printf(), которая должна вернуть -1... ну в теории. Запускаем и видим:

$ ./main 
printf: Bad file descriptor
code is 4

Это как так-то? Функция явно завершилась с ошибкой, но вернула при этом число байт.

Система линукс, компилятор gcc.


Ответы (1 шт):

Автор решения: user7860670

printf заимствует часть требований от fprintf, в т.ч. чтобы stdout указывал на файловый поток. Ломая stdout (причем именно ломая, так как закрывается он посредством fclose, а закрытие нижележащего файлового дескриптора переводит поток в неконсистентное состояние), вы нарушаете требования к входящим параметрам для вызова printf и получаете Неопределенное Поведение.

Как продолжение, было бы интересно узнать, когда же printf может все-таки возвратить ошибку при корректном вызове? По идее, такой сценарий можно устроить, если например запустить этот процесс как дочерний, передав ему в качестве дескриптора stdout вход от pipe, и затем закрыв выход в родительском процессе.

→ Ссылка