Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是‘;安全’;要删除()打开文件?_C_Stdio - Fatal编程技术网

C 是‘;安全’;要删除()打开文件?

C 是‘;安全’;要删除()打开文件?,c,stdio,C,Stdio,我考虑在我的程序中添加输入和输出文件使用相同文件名的可能性,以便它将替换输入文件 由于处理后的文件可能相当大,我认为最好的解决方案是首先打开文件,然后将其删除并创建一个新文件,即: /* input == output in this case */ FILE *inf = fopen(input, "r"); remove(output); FILE *outf = fopen(output, "w"); (当然,添加了错误处理) 我知道并不是所有系统都允许我删除打开的文件,只要remove

我考虑在我的程序中添加输入和输出文件使用相同文件名的可能性,以便它将替换输入文件

由于处理后的文件可能相当大,我认为最好的解决方案是首先打开文件,然后将其删除并创建一个新文件,即:

/* input == output in this case */
FILE *inf = fopen(input, "r");
remove(output);
FILE *outf = fopen(output, "w");
(当然,添加了错误处理)

我知道并不是所有系统都允许我删除打开的文件,只要
remove()
在这种情况下失败,这是可以接受的

但我担心,如果没有任何系统允许我删除打开的文件,然后无法读取其内容

C99标准将这种情况下的行为指定为“实现定义”;苏斯甚至没有提到这个案子

你的看法/经验是什么?我一定要担心吗?我应该避免这样的解决方案吗

编辑:请注意,这不是一些主线功能,而是在用户指定输入和输出文件的文件名相同的情况下的“最后手段”


编辑:好的,然后再问一个问题:在这种特殊情况下,我提出的解决方案是否可能比仅以写方式打开输出文件(即,如上所述,但没有
remove()
调用)更有害.

据我所知,所有允许删除打开的文件的系统都会对文件节点执行某种形式的引用计数。因此,删除文件会删除目录条目,但文件节点本身仍然有一个来自打开文件句柄的引用。在这样的实现中,删除文件显然不会影响继续读取它的能力,我发现很难想象有任何其他合理的方法来实现这种行为。

我总是在Linux/Unix上使用这种方法。绝不在Windows、OS/2或(抖动)DOS上使用。您还关心其他平台吗


这种行为在使用临时磁盘空间时非常有用——打开文件进行读/写操作,然后立即将其删除。它会在程序退出时自动清除(出于任何原因,包括断电),并使其他人更难(但并非不可能)监视它(/proc可以提供线索,如果您有该进程的读取权限)。

不,它不安全。它可能在您的文件系统上工作,但在其他文件系统上失败。或者它可能会间歇性地失败。这实际上取决于您的操作系统和文件系统。要深入了解Solaris,请参见以下内容

看一看。此选项的工作方式是将输出写入临时文件,然后复制原始文件。这是唯一安全、兼容的方法

你也应该考虑到你的程序在任何时候都会失败,因为停电或者进程被杀死。如果发生这种情况,则原始文件将丢失。此外,对于具有引用计数的文件系统,您不会通过临时文件解决方案节省任何空间,因为在关闭输入文件之前,两个文件都必须存在于磁盘上


如果文件很大,空间很宝贵,开发人员的时间很便宜,那么您可以打开一个单独的文件进行读/写,并确保您的写指针不会超过您的读指针。

我关心的是,Pavel Minaev是Microsoft的开发人员,他对windows的看法正好相反……是的,我知道这些问题。如果用户为输入和输出指定了相同的文件,我更考虑使用它来减少epic失败的可能性。这至少是始终将输出写入临时文件的价值的一部分。此外,您可能需要小心地将输入重命名为第二个临时值,将输出临时值重命名为最终名称,然后,只有在所有操作都成功的情况下,才删除输入。如果用例希望将输入保留为.bak或类似的格式,那么您将相应地执行更多的洗牌操作。您确实是对的,我完全忘记了这一点。问题是,这将与我当前的输出方法相冲突,但我会在下一个问题中询问它是否有用;它不是原子的,并且会有一个窗口,在该窗口中,文件根本不存在正确的名称。如果你真的想保留一个“备份”,你可以在重命名输出临时文件之前硬链接到输入文件。请提醒我不要在我有价值的数据文件上使用你的应用程序。自述文件中的专用警告是否足够,或者我是否应该在ebuild的
pkg_postinst()
中添加一个警告?(;如果两个文件名相同,您是否确实应该继续?您是否可以在日志或控制台中发出警告,要求用户输入不同的名称?我考虑过这一点,但为了正确执行,我应该在文件名中添加一些损坏;这些文件仍然可以有不同的名称,但可以硬链接。在这种情况下,我可以
stat()
两者都是,并且比较dev/ino,但这不是很好移植,可能会导致竞争条件(输入文件是通过库打开的,所以我不能
fstat()
it)。最后,值得付出所有的努力吗?