不带fclose()的文件*重新分配可以吗?

不带fclose()的文件*重新分配可以吗?,c,file-io,fopen,fclose,file-pointer,C,File Io,Fopen,Fclose,File Pointer,假设我有以下代码: FILE*x=fopen(“story.txt”,r); 如果(x!=NULL) { x=fopen(“story.txt”,wb);/*您刚刚泄漏了一个文件句柄。如果您做得足够多,您将用完可分配的打开文件句柄,所有打开文件的尝试都将失败。不要这样做。fclose您的文件*s 没有理由认为“内存区域”会在这里被覆盖;您正在覆盖指针,而不是它指向的内容,它指向的是与文件相关的结构(stdiobuffers,底层内核文件句柄的描述符,等等)。它不会覆盖所指向的内存,就像将第二个m

假设我有以下代码:

FILE*x=fopen(“story.txt”,r);
如果(x!=NULL)
{

x=fopen(“story.txt”,wb);/*您刚刚泄漏了一个文件句柄。如果您做得足够多,您将用完可分配的打开文件句柄,所有打开文件的尝试都将失败。不要这样做。
fclose
您的
文件*
s


没有理由认为“内存区域”会在这里被覆盖;您正在覆盖指针,而不是它指向的内容,它指向的是与文件相关的结构(
stdio
buffers,底层内核文件句柄的描述符,等等)。它不会覆盖所指向的内存,就像将第二个
malloc
分配给同一个指针会覆盖第一个
malloc
所指向的内存一样;在这两种情况下,您都会丢失原始指针,转而使用新指针,从而泄漏第一次资源获取。

主要问题是许多操作系统都存在漏洞限制每个进程可以拥有的打开文件的数量,这是因为每个进程的内核数据结构中都有一个包含所有文件的数组,必须有足够的空间容纳进程中的所有文件

如果覆盖指针,C中就不会有垃圾收集(如果不是自己做的话,通常=从不),因此系统不会知道指针指向的
文件
结构应该是空闲的,这将导致内存泄漏。但更糟糕的泄漏是有限的操作系统资源泄漏

退出程序后,情况自然会自行解决-所有未关闭的文件都将关闭并刷新。但是,将
fclose
放在那里真的有那么难吗

FILE *x = fopen("story.txt", r);
if (x != NULL)
{
    fclose(x);
    x = fopen("story.txt", wb); // <- this certainly does not leak any more
FILE*x=fopen(“story.txt”,r);
如果(x!=NULL)
{
fclose(x);

x=fopen(“story.txt”,wb);//ShadowRanger好的,这是不好的,但也许你可以更详细地告诉我你所说的“泄露文件句柄”是什么意思以及我是怎么做到的?我是新来的,所以我不明白:)@user13863346,一个进程可以有多少个打开的文件句柄是有限制的。如果你不关闭就打开fds,你可能会用完。@ikegami我看到了0_0@user13863346:说得清楚一点,如果你在一个程序中只做了一次,再也不做了,你可能就不会因此而受苦了。泄漏检测器可能会捕捉到它,但程序会运行,甚至当进程最终退出,操作系统回收所有进程资源时,你泄漏的句柄也会关闭。但这是一个非常坏的习惯;当你开始如果在循环中不是这样的话,您可能会面临文件句柄耗尽的风险。此外,任何看到这样一个明显错误的维护人员都会认为原始作者是一个草率的编码员,并且必须花费更多的时间来验证代码是否损坏。啊,这样“内存区域”就不会被覆盖,嗯……我不认为我是在重写指针对于我的实际程序,我在校对时发现了两个点,如果它错了,我会纠正它,不是很大的改变。在stdio.h中有一个
FOPEN\u MAX
的定义,它是可以打开的最大文件数(使用
FOPEN
)在任何时候。这包括3个标准流:stdin、stdout和stderr。C标准说,“FOPEN_MAX的值至少应为8”因此,从理论上讲,如果程序在不关闭文件的情况下重新分配指针5次,
fopen
函数可能不再工作。它可能每次都返回NULL。您错过了传递的不是
file*x
,而是存储
fopen(“story.txt”、“wb”)返回的地址
进入指针变量
x
。因此
x
被覆盖,而不是
*x
@user3386109出于好奇,在POSIX和windows机器上,
FOPEN_MAX
的值是多少?
FOPEN_MAX
的值在一个
.h
文件中(例如,
stdio.h
或其他一些它做了一个
#include
on)。但是,一个简单的方法是:
printf(“FOPEN\u MAX=%d\n”,FOPEN\u MAX);
作为
main
的第一行。但是,在linux下它是16,所以我不确定这是开放流数量的限制(例如1024将是一个更合理的数字).TLDR:就是这样。因此,如果你真的需要使用每个可用文件,代码应该查看
FOPEN_MAX
\u POSIX_OPEN_MAX
,看看有多少可用文件。如果你想知道你的机器上的限制是什么,只需按照@CraigEstey的建议查看宏即可。Antti,谢谢你的回答。没有这一点也不难:D,我已经做到了,我只是想知道会有什么后果:)