我编写了一个简单的库文件,其中包含一个从任意大小的文件中读取行的函数。该函数通过传入堆栈分配的缓冲区和大小来调用,但如果行太大,则初始化一个特殊的堆分配缓冲区并用于传回更大的行。
这个堆分配的缓冲区是函数范围的并声明为静态的,当然在开始时初始化为 NULL。我在函数开头写了一些检查,检查堆缓冲区是否为非空;如果是这种情况,则上一行读取的内容太长。自然地,我释放了堆缓冲区并将其设置回 NULL,认为下一次读取可能只需要填充堆栈分配的缓冲区(即使在我们的应用程序中,应该很少看到超过 1MB 的行!)。
通过仔细阅读和运行一些测试,我已经仔细阅读了代码并对其进行了相当彻底的测试。我有理由相信保持以下不变量:
- 如果只需要堆栈缓冲区,则函数返回时堆缓冲区将为空(并且不会泄漏任何内存)。
- 如果堆缓冲区不为空,因为它是需要的,它将在下一个函数调用时被释放(如果需要,可能在下一行中重用)。
但是我想到了一个潜在的问题:如果文件中的最后一行太长,那么由于该函数可能不会再次调用,我不确定我有什么方法可以释放堆缓冲区——它是函数毕竟,范围很广。
所以我的问题是,如何在函数范围的静态指针中释放动态分配的内存,最好不要再次调用该函数?(理想情况下也不要让它成为全局变量!)
可根据要求提供代码。(抱歉,我现在无法访问。而且我希望这个问题足够笼统且解释清楚,因此不需要它,但无论如何,请随时消除我的这个想法!)
编辑:我觉得我应该添加一些关于函数用法的注释。
这个特定的函数以从文件中连续读取行的形式使用,然后立即复制到 POD 结构中,每个结构一行。这些是在读取文件时在堆上创建的,并且每个结构都有一个 char 指针,其中包含文件中的一行(清理后的版本)。为了使这些持续存在,必须进行复制。(这是许多答案中提出的主要反驳之一——哦,不,需要复制这条线,哦,亲爱的我)。
至于多线程,正如我所说,这是为了串行使用而设计的。不,它不是线程安全的,但我不在乎。
不过,感谢您的众多回复!当我有时间时,我会更彻底地阅读它们。目前,我倾向于传递一个额外的指针或重新设计函数,以便在fgets
显示 EOF 时,我可能只是在那里构建释放逻辑,希望用户不必担心它。