当我阅读的文档时fflush
,它说如果成功则返回 0,否则返回 EOF(我的机器上的 EOF 为 -1)。(请参阅或)
因此我创建了以下示例:
#include<cstdio>
#include<iostream>
int main()
{
FILE* fp = std::fopen("/tmp/test", "w+");
std::fclose(fp);
std::cout << std::fflush(fp) << std::endl;
return 0;
}
g++ minimal.cpp
如果我使用或进行编译g++ -O2 -DNDEBUG minimal.cpp
,它会打印 -1。这正是我所期望的。
g++ minimal.cpp -fsanitize=address
但是,当我用或编译它时g++ minimal.cpp -fsanitize=thread
,它只打印 0。
我也可以用 clang 重现同样的问题。
怎么会这样?
我在我的 Debian 12 amd64 机器上使用了 g++-12 和 clang-15。结果始终相同(即fflush
返回 0 而不是 -1)。
1
最佳答案
1
根据 fflush 的文档(C99 标准中的 7.19.5.2):
如果 stream 指向一个输出流或一个未输入最近操作的更新流,则 fflush 函数会导致将该流的任何未写入数据传送到主机环境并写入文件;否则,行为未定义。
这意味着如果您在未打开的文件上调用它(就像您正在做的那样),您会得到未定义的行为。
这是因为 C 标准在历史上是一个“事实上的”标准,它收集了不同实现所做的所有常见事情,而不是试图“强迫”不同的实现者实现相同的事情。因此,在很多地方(尤其是错误或极端情况),不同的实现在历史上做了不同的事情,所以标准只是说“未定义”。
5
-
的链接可能对 OP 有用,因此添加到这里。
– -
@JesperJuhl C 中是否有类似的 UB 描述?尽管 C 和 C++ 对未定义行为的概念非常相似,但仍存在一些关键差异。并且本例中的未定义行为源自 C 标准,而非 C++ 标准。
– -
@peter 它们是相同的概念。C:“使用不可移植或错误的程序构造或错误数据时的行为,本国际标准对此不作要求”;C++:“本文档对此不作要求的行为”。
– -
@molbdnilo 我知道定义是相同的。但 Jesper 给出的链接也讨论了其含义,并提供了涉及 C++ 代码的具体示例。考虑到这里的人们经常因为询问有关 C 和 C++ 的问题而大吵大闹,而且这个答案引用了 C 标准,如果有与 C 相关的信息(在这种情况下我不知道) – 将是合适的。
– -
@Peter是关于 C 的相应页面。
–
|
std::fflush(fp)
无论使用什么清理器,之后std::fclose(fp)
都是 UB::对流的任何进一步访问都会导致未定义的行为。–
|