请注意以下终端输出:
$ 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!
Run Code Online (Sandbox Code Playgroud)
C11标准的第7.21.6.1节说:
fprintf函数将输出写入stream指向的流,在指向格式的字符串的控制下,该格式指定后续参数如何转换为输出.
接下来是转换说明符的描述,但结尾为:
返回
fprintf函数返回传输的字符数,如果发生输出或编码错误,则返回负值.
看来假定文件在第二次fprintf调用时关闭,它应该失败,但事实并非如此.我在Kubuntu Trusty 64位上使用Clang 4.0.1和GCC 4.8.4对此进行了测试.
我对标准的理解是否有缺陷,还是应该提交错误?
引用C99,7.19.3文件:
- [...]
FILE关闭文件后,指向对象的指针的值是不确定的(包括标准文本流).
从而:
fclose(ofile);
success = fprintf(ofile, "Trying again...");
Run Code Online (Sandbox Code Playgroud)
第二行读取ofile,其后(后fclose)具有不确定的值.这有未定义的行为.
另见附件J.2:
在以下情况下,行为未定义:[...]
具有自动存储持续时间的对象的值在不确定时使用(6.2.4,6.7.8,6.8).
在关联文件关闭后,将使用指向FILE对象的指针的值(7.19.3).