fflush() 始终 returns 0 但将 errno 设置为 11(资源暂时不可用)

fflush() always returns 0 but sets errno to 11 (resource temporarily unavailable)

每当我调用 vasprintf() 函数时,errno 都会设置为 11(资源暂时不可用)。但是,似乎一切都在正常运行。为了更好地理解错误的来源,我在 uclibc 中找到了 vasprintf() 的实现并将其放入我的程序中。我发现 fflush()errno 设置为 11。但是,所有迹象都表明代码运行正常。例如,fflush() 的 return 值为 0open_memstream()size 值在文件关闭后正确更新。输出缓冲区已正确更新。我还在无限循环中调用了 output() 函数来查看是否有任何内存泄漏,但我发现在几千个循环中内存没有增加。

如果关闭文件并写入数据,是否真的有错误需要解决?

#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

#

这是C标准的精妙之处。大多数库函数都允许将 errno 设置为非零值 ,即使它们成功了 。您应该只在函数已经以其他方式报告失败后才查看 errno

两个重要说明:

  • 有极少数函数可能会通过将 errno 设置为非零值来报告失败 只有 ;最突出的是 strto* 函数。要正确调用这些函数,您必须在调用它们之前将 errno 设置为零,然后检查它是否立即变为非零。

  • 标准保证 C 库函数 从不errno 设置为零。

标准语:N1570 section 7.5 paragraph 3

The value of errno in the initial thread is zero at program startup (the initial value of errno in other threads is an indeterminate value), but is never set to zero by any library function. The value of errno may be set to nonzero by a library function call whether or not there is an error, provided [the documentation for the specific function doesn't say otherwise].