封闭文件不应该fprintf失败吗?

时间:2017-10-28 00:12:44

标签: c printf

请注意以下终端输出:

$ 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对此进行了测试。

我对标准的理解是否有问题,还是应该提交错误?

2 个答案:

答案 0 :(得分:7)

引用C99, 7.19.3文件

  
      
  1. [...]关联文件关闭后,指向FILE对象的指针的值是不确定的(包括标准文本流)。
  2.   

因此:

fclose(ofile);
success = fprintf(ofile, "Trying again...");

第二行从ofile读取,(fclose之后)具有不确定的值。这有不明确的行为。

另见附件J.2:

  
      
  1. 在以下情况下,行为未定义:   [...]

         
        
    • 具有自动存储持续时间的对象的值在不确定时使用(6.2.4,6.7.8,6.8)。

    •   
    • 在关联文件关闭后使用指向FILE对象的指针的值(7.19.3)。

    •   
  2.   

答案 1 :(得分:4)

不,这不是错误。根据{{​​1}}:

,您正在做的是未定义的行为
  

在以下情况下,行为未定义:

     

...

     
      
  • 关联文件关闭后使用指向All对象的指针的值(7.21.3)
  •   

因此,在这种情况下,实现可以随意做任何事情。根据引用,Name部分提供了有关此问题的更多详细信息。