C 如果文件已打开,fopen是否返回空指针?

C 如果文件已打开,fopen是否返回空指针?,c,file-handling,mingw32,C,File Handling,Mingw32,我假设fopen在文件已经打开时返回空指针。但若文件已经在w模式下打开,fopen看起来不会返回NULL。下面是我用来尝试的代码,我没有得到任何错误。我尝试使用mingw32以及TDM-GCC-64编译器。如果我没有错,如果文件已经打开,C++会出错。 #include<stdio.h> int main() { FILE *fp1, *fp2; fp1 = fopen("file1.txt", "w");

我假设fopen在文件已经打开时返回空指针。但若文件已经在w模式下打开,fopen看起来不会返回NULL。下面是我用来尝试的代码,我没有得到任何错误。我尝试使用mingw32以及TDM-GCC-64编译器。如果我没有错,如果文件已经打开,C++会出错。
#include<stdio.h>

int main()
{
    FILE *fp1, *fp2;
    
    fp1 = fopen("file1.txt", "w");
    fp2 = fopen("file1.txt", "w");
    
    if(fp2 == NULL)
    {
        printf("Error in opening file\n");
        return(0);
    }
    
    // Edit: added following code to check the behavior if write operation
    // is performed simultaneously
    
    fputc('A', fp1);
    fputc('M', fp1);
    fputc('S', fp1);
    fputc('B', fp2);
    
    fclose(fp1);
    fclose(fp2);
    
    return 0;
}

编辑:添加额外的代码,将一些数据写入fp1和fp2,并查看其行为。如果执行,file1.txt包含数据BMS,并且似乎是正确的行为,fp1和fp2按照预期独立移动。首先使用fp1编写AMS,然后使用fp2将A替换为B,最终输出为BMS。

根据C标准7.19.3.8,它是实现定义的:

打开其他非临时文件的函数需要文件名,即字符串。构成有效文件名的规则由实现定义。同一个文件是否可以同时打开多次也是由实现定义的

除此之外,还有其他原因不鼓励使用,例如:

某些实现不允许同时打开同一文件的多个副本。因此,可移植代码不能依赖于如果违反此规则将发生什么。即使在没有完全无法打开已经打开的文件的实现上,也需要一段时间的检查,存在使用时间竞争条件,其中第二个打开的文件可能会由于文件被移动或删除而在与第一个不同的文件上运行。请参阅FIO45-C。访问文件时避免TOCTOU竞争条件以了解TOCTOU竞争条件的更多详细信息


根据C标准7.19.3.8,其定义为:

打开其他非临时文件的函数需要文件名,即字符串。构成有效文件名的规则由实现定义。同一个文件是否可以同时打开多次也是由实现定义的

除此之外,还有其他原因不鼓励使用,例如:

某些实现不允许同时打开同一文件的多个副本。因此,可移植代码不能依赖于如果违反此规则将发生什么。即使在没有完全无法打开已经打开的文件的实现上,也需要一段时间的检查,存在使用时间竞争条件,其中第二个打开的文件可能会由于文件被移动或删除而在与第一个不同的文件上运行。请参阅FIO45-C。访问文件时避免TOCTOU竞争条件以了解TOCTOU竞争条件的更多详细信息


那么,在发布的代码中会发生什么呢?@Rajesh这是关于文件共享的,在Windows上,如果您的lib实现使用SH_DENYNO调用_fsopen,那么另一个程序或同一个程序。。。也可以多次打开文件进行写入。将要发生的事情取决于实现和底层操作系统并发写入并不是那么容易,至少在Windows上是这样。但是请注意,默认fopen假定共享,因为通常*nix操作系统使用其他同步原语。请参见fcntlCit:在大多数库实现中,errno变量也设置为故障时的系统特定错误代码。那么在发布的代码中会发生什么?@Rajesh这是关于文件共享的,在Windows上,如果您的lib实现使用SH_DENYNO调用_fsopen,例如,则另一个程序或同一个程序。。。也可以多次打开文件进行写入。将要发生的事情取决于实现和底层操作系统并发写入并不是那么容易,至少在Windows上是这样。但是请注意,默认的fopen假定共享,因为*nix操作系统通常使用其他同步原语。请参见fcntlCit:在大多数库实现中,errno变量也设置为故障时的系统特定错误代码。我添加了额外代码并编辑了帖子。如果我们尝试同时使用两个文件指针进行编写,那么这两个文件指针都会被写入,并且文件指针会被独立处理,我想这是正确的行为。如果我们尝试同时使用两个文件指针进行写入,那么两个文件指针都会被写入,并且文件指针会被独立处理,我想这是正确的行为。