2014-10-27 148 views
0

的fopen示例失败文件被删除后文件打开问题。的fopen状态在VC

#include <stdio.h> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    FILE * pFile; 
    for(int i=0; i < 1000000; i++) 
    { 
     bool ret = remove("C:\\abc.txt"); 
     pFile = fopen ("C:\\abc.txt","w"); 
     if (pFile!=NULL) 
     { 
      fputs ("fopen example",pFile); 
      fclose (pFile); 
     } 
     else 
     { 
      printf("%d fopen() fails \n", count); 
     } 
    } 
    return 0; 
} 

在此,删除被调用,PFILE =的fopen( “C:\的abc.txt”, “W”)之后;被调用,

有时即使在C:\中,abc.txt文件在remove被调用后也不存在,但fopen pFile指针为null。

这是一些不总是转载。在这个例子中,这个问题被转载50/60次。

请提出一些解决方案。

+3

您是否尝试过检查errno变量?它可能会被系统设置为一些错误代码,这可能会帮助你解决这个问题,你可以使用perror来收集更多的信息。也看看http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html – fjanisze 2014-10-27 09:15:39

+0

看起来像一个竞争条件。底层文件系统中可能的优化可以让'remove'在真正清除所有内容之前返回,并立即创建具有相同名称的文件。尝试在删除和创建之间添加短暂的睡眠:它应该起作用。 – 2014-10-27 09:21:54

+0

如果您想以“w”模式打开文件,请删除文件,我认为您不需要。 – BLUEPIXY 2014-10-27 09:51:12

回答

1

如果您已经确定是是竞争条件在底层文件系统中的问题,要解决它是(通过BLUEPIXY的建议),以简单地去掉remove调用正确的方法:

pFile = fopen ("C:\\abc.txt","w"); 

将创建该文件,如果它不存在,并将其截断为0大小(如果它存在),那么正是您所需要的。

+0

我正在使用包装函数,其中给出fopen调用。如果文件被删除,它将以写模式打开,否则以rb +模式打开。因此,在应该删除并重新创建的情况下,会出现问题。 另外我检查了remove()函数的返回值,以确认删除是否成功,令我惊讶的是,我发现有时删除返回成功的值,并进一步fopen失败给予“权限被拒绝”作为错误,有时remove()函数失败但fopen是成功的。删除()似乎是不可靠的函数。 – Aakash 2014-10-27 11:16:20

+0

@Aakash:'remove'不是靠它的一个不可靠的函数。但是在Windows下,如果在打开的文件上调用(特殊访问模式除外),它会失败,所以你有相同的种族问题。恕我直言,你应该重新考虑你的算法,不要执行移除调用。 *在您的用例条件*中是不安全的。 – 2014-10-27 11:35:20

+0

谢谢您的信息。我会检查其他方式。谢谢。 – Aakash 2014-10-28 03:13:06

0

如果您需要在文件被移除后确定创建文件,您可以延迟打开文件,直到您确认删除了旧的“abc.txt”文件。

对于您需要引入一些循环,以确认它像下面,

bool ret = remove("C:\\abc.txt"); 
FILE * rFile; 
while(true) 
{ 
    rFile = fopen ("C:\\abc.txt","r"); 
    if(rfile == null) 
     break; //File Removed confirmed!! 
    else 
     sleep(100); //Loop around again... 
} 
pFile = fopen ("C:\\abc.txt","w"); 
if (pFile!=NULL)