C 标准库角落案例

发布于 2024-09-08 09:09:29 字数 560 浏览 6 评论 0原文

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

#include <stdio.h>

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

请注意,我尝试从 stderr 读取。

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

xy

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

此行为是否正确,或者这是编译器库错误?我在任何地方都找不到任何描述 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;
}

Notice that I try to read from stderr.

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

xy

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).

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

转角预定愛 2024-09-15 09:09:29

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

当使用更新模式打开文件时('+' 作为上面 mode 参数值列表中的第二个或第三个字符),输入和输出都可能在关联的流上执行。但是,如果没有对 fflush 函数的中间调用,输出后面不应直接跟输入,并且在没有对文件定位函数的中间调用的情况下,输入后面不应直接跟输出,除非输入操作遇到文件结尾。

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

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

C99 says in 7.19.5.3 (fopen), paragraph 6:

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文