请注意以下终端输出:
$ cat fprintf-closed-file.c
#include <stdio.h>
int main()
{
FILE * ofile = fopen("/tmp/goo", "w");
int success = fprintf(ofile, "Hello %s\n", "World!");
printf("Success: %d\n", success);
fclose(ofile);
success = fprintf(ofile, "Trying again...");
printf("Success: %d\n", success);
}
$ clang -o fprintf-closed-file fprintf-closed-file.c
$ ./fprintf-closed-file
Success: 13
Success: 15
$ cat /tmp/goo
Hello World!
C11标准的第7.21.6.1节说:
fprintf函数将输出写入stream指向的流, 在格式指向的字符串的控制下,指定如何 后续参数将转换为输出。
后面是转换说明符的描述,但以:
结尾返回
fprintf函数返回字符数 传输,如果输出或编码错误,则为负值 发生。
考虑到文件在第二次fprintf
调用时关闭,它似乎会失败,但事实并非如此。我在Kubuntu Trusty 64位上使用Clang 4.0.1和GCC 4.8.4对此进行了测试。
我对标准的理解是否有问题,还是应该提交错误?
答案 0 :(得分:7)
引用C99, 7.19.3文件:
- [...]关联文件关闭后,指向
醇>FILE
对象的指针的值是不确定的(包括标准文本流)。
因此:
fclose(ofile);
success = fprintf(ofile, "Trying again...");
第二行从ofile
读取,(fclose
之后)具有不确定的值。这有不明确的行为。
另见附件J.2:
- 醇>
在以下情况下,行为未定义: [...]
具有自动存储持续时间的对象的值在不确定时使用(6.2.4,6.7.8,6.8)。
在关联文件关闭后使用指向FILE对象的指针的值(7.19.3)。
答案 1 :(得分:4)
不,这不是错误。根据{{1}}:
,您正在做的是未定义的行为在以下情况下,行为未定义:
...
- 关联文件关闭后使用指向
All
对象的指针的值(7.21.3)
因此,在这种情况下,实现可以随意做任何事情。根据引用,Name
部分提供了有关此问题的更多详细信息。