c语言 - fprintf 不应该在关闭的文件中失败吗?



请观察以下终端输出:

$ cat fprintf-closed-file.c
#include <stdio.h>
int main()
{
    FILE * ofile = fopen("/tmp/goo", "w");
    int success = fprintf(ofile, "Hello %sn", "World!");
    printf("Success: %dn", success);
    fclose(ofile);
    success = fprintf(ofile, "Trying again...");
    printf("Success: %dn", 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 函数将输出写入流指向的流, 受指定如何 后续参数将转换为输出。

后跟转换说明符的说明,但结尾为:

返回

fprintf 函数返回字符数 传输,如果输出或编码错误,则为负值 发生。

看起来,鉴于文件在第二次fprintf调用时已关闭,它应该会失败,但事实并非如此。我在 Kubuntu Trusty 64 位上使用 Clang 4.0.1 和 GCC 4.8.4 对此进行了测试。

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

引用C99,7.19.3文件

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

因此:

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

第二行从ofile读取,它(在fclose之后)有一个不确定的值。这具有未定义的行为。

另见附件J.2:

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

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

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

不,这不是错误。您正在做的是未定义的行为,如C11 Annex J.2

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

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

因此,在这种情况下,实现可以自由地做任何它想做的事情。根据引文,第7.21.3节提供了有关此事的更多详细信息。

最新更新