fflu sh () Always Retruns 0, но устанавливает errno равным 11 (ресурс временно недоступен) - PullRequest
1 голос
/ 06 марта 2020

При каждом вызове функции vasprintf() errno устанавливается равным 11 (ресурс временно недоступен). Тем не менее, похоже, что все работает правильно. Чтобы лучше понять источник ошибки, я нашел реализацию vasprintf() в uclib c и поместил ее в мою программу. Я обнаружил, что fflush() устанавливает errno в 11. Однако все признаки того, что код работает правильно. Например, возвращаемое значение из fflush() равно 0. Значение size для open_memstream() корректно обновляется после закрытия файла. Выходной буфер обновляется правильно. Я также вызвал функцию output() в бесконечном l oop, чтобы проверить, не просачивалась ли память, но я не увидел увеличения объема памяти за несколько тысяч циклов.

Если файл был закрыт и данные были написано, действительно ли ошибка для устранения?

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

void output(int type, const char *fmt, ...)
{
    FILE *f;
    size_t size;
    int rv = -1;
    int fclose_return = 5;
    int fflush_return = 5;
    va_list ap;
    char *output_str_no_prefix = NULL;
    va_start(ap, fmt);
//  vasprintf(&output_str_no_prefix, fmt, ap);

    if ((f = open_memstream(&output_str_no_prefix, &size)) != NULL) {
        rv = vfprintf(f, fmt, ap);


        errno = 0;
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fflush_return);
        fflush_return = fflush(f);
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fflush_return);

        errno=0;
        fclose_return = fclose(f);
        printf("%s: errno(%d): %s -- Return Value: %d\n",
                __func__, errno, strerror(errno), fclose_return);

        if (rv < 0) {
            free(output_str_no_prefix);
            output_str_no_prefix = NULL;
        } else {
            output_str_no_prefix = realloc(output_str_no_prefix, rv + 1);
        }
    }
    va_end(ap);
    printf ("%s\n", output_str_no_prefix);
    free(output_str_no_prefix);
}

int main () {
    output(0, "Hello! -- %d\n", 4);
    return 0;

}

Вот вывод для программы выше.

# /data/HelloWorld
output: errno(0): Success -- Return Value: 5
output: errno(11): Resource temporarily unavailable -- Return Value: 0
output: errno(0): Success -- Return Value: 0
Hello! -- 4

#

1 Ответ

4 голосов
/ 06 марта 2020

Это тонкость стандарта C. Большинству библиотечных функций разрешено устанавливать errno в ненулевое значение , даже если они завершаются успешно . Вы должны смотреть на errno только после того, как функция уже сообщила о сбое другим способом.

Два важных замечания:

  • Существует очень мало функций, которые могут сообщить об ошибке только , установив errno в ненулевое значение; наиболее выдающимися являются strto* функции. Для правильного вызова этих функций вы должны установить errno в ноль непосредственно перед вызовом, а затем проверить, не стало ли оно ненулевым сразу после этого.

  • Стандарт гарантирует, что C библиотечные функции никогда установить errno на ноль.

Стандартное: N1570 раздел 7.5 параграф 3

Значение Значение errno в исходном потоке равно нулю при запуске программы (начальное значение errno в других потоках является неопределенным значением), но оно никогда не устанавливается равным нулю какой-либо библиотечной функцией. Значение errno может быть установлено в ненулевое значение при вызове библиотечной функции независимо от того, есть ли ошибка, если [документация для указанной функции c не говорит иначе].

...