C 标准库角落案例 [英] C standard library corner case

查看:23
本文介绍了C 标准库角落案例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序是有效的 C 程序吗?

Is the following program a valid C program?

#include <stdio.h>

int main()
{
    fwrite("x", 1, 1, stderr);
    fflush(stderr);
    fgetc(stderr);
    fwrite("y", 1, 1, stderr);
    return 0;
}

请注意,我尝试从 stderr 读取数据.

Notice that I try to read from stderr.

当我在 Visual C++ 2008 中编译并运行它时,我得到以下输出:

When I compile it in Visual C++ 2008, and run it, I get the following output:

xy

这是有道理的.但是,当我将 stderr 重定向到一个文件 (test.exe 2> foo.txt) 时,我得到一个调试断言失败"窗口显示消息:不一致的流计数.在连续读取和写入之间刷新".在读取和写入之间添加 fflush 确实可以解决问题.(这发生在调试版本中.在发布版本中,第二次写入会默默地失败).

which makes sense. However, when I redirect stderr to a file (test.exe 2> foo.txt), I get a "Debug Assertion Failed" window with the message: "Inconsistent Stream Count. Flush between consecutive read and write". Adding a fflush between the read and write does fix the problem. (This happens in debug build. In release builds, the second write silently fails).

这种行为是否正确,还是编译器库错误?我在任何地方都找不到任何描述在 C 中读取或写入何时非法的规则.

Is this behavior correct, or is this a compiler library bug? I couldn't find anywhere any rules describing when reads or writes are illegal in C.

推荐答案

C99 在 7.19.5.3 (fopen), 第 6 段中说:

C99 says in 7.19.5.3 (fopen), paragraph 6:

当文件以更新模式打开时('+' 作为上述 mode 参数值列表中的第二个或第三个字符),输入和输出都可能在关联的流上执行.但是,输出不应直接跟随输入而不介入对 fflush 函数的调用 [...],并且输入不应直接跟随输出而不介入对文件定位函数的调用,除非输入操作遇到文件尾.

When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function [...], and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.

祝贺您在实践中发现了这个极端情况.库实现是完全正确的,因为您违反了上面引用的.

Congratulations for discovering this corner case in practice. The library implementation is completely correct, since you violate the shall quoted above.

顺便说一下,从 stderr 读取数据并不少见.当 stdinstdout 被重定向并且没有终端可用时,这很有用.虽然 C99 不保证它是可读的,但我记得在类似 POSIX 的系统上的一些情况下,这实际上已经完成了.

And by the way, it is not uncommon to read from stderr. This is useful when stdin and stdout are redirected and no terminal is available. Although C99 doesn't guarantee it to be readable, I remember some cases on POSIX-like systems where this had actually been done.

这篇关于C 标准库角落案例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆