谁免费的setvbuf缓冲区?

Eva*_*ran 7 c buffer stdio

所以我一直在深入研究如何实现libc的stdio部分,并且我遇到了另一个问题.看着man setvbuf我看到以下内容:

当在文件上发生第一个I/O操作时,调用malloc(3),并获得缓冲区.

这是有道理的,malloc除非您实际使用它,否则您的程序不应该包含I/O. 我对此的直觉反应是,libc将在这里清理它自己的烂摊子.我只能假设它是因为valgrind报告没有内存泄漏(他们当然可以做一些肮脏的事情而不是通过malloc直接分配它......但我们会假设它malloc现在用于字面意义).

但是,您也可以指定自己的缓冲区......

int main() {
    char *p = malloc(100);
    setvbuf(stdio, p, _IOFBF, 100);
    puts("hello world");
}
Run Code Online (Sandbox Code Playgroud)

哦不,内存泄漏!valgrind证实了这一点.因此,似乎只要stdio自己分配一个缓冲区,它就会被自动删除(最迟在程序退出时,但可能在流程上关闭).但是如果你明确指定缓冲区,那么你必须自己清理它.

虽然有一个问题.该手册页也说明了这一点:

您必须确保时间流关闭时buf指向的空间仍然存在,这也会在程序终止时发生.例如,以下内容无效:

现在这对于标准流来说变得越来越有趣.如何正确清理手动分配的缓冲区,因为它们在程序终止时关闭?我可以想象一下文件结构中的"在关闭标志时清理它",但是它会变得毛茸茸,因为如果我读到这个就做这样的事情:

setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");
Run Code Online (Sandbox Code Playgroud)

由于这句话,标准库将导致2次分配:

如果参数buf为NULL,则只影响模式; 将在下一个读或写操作上分配新缓冲区.

编辑:我的问题的附录.因为很明显我必须free传递给任何缓冲区setvbuf,如果我确实使用它,stdout有什么实用的方法free吗?它必须活到程序结束.我能想到的最好的就是fclose(stdout)释放它或使用静态缓冲区,正如有些人提到的那样.我问,因为它似乎是一个尴尬的设计决定.

out*_*tis 3

也来自手册页(至少在我的系统上):

如果 buf 不为 NULL,则调用者有责任在关闭流后 free(3) 此缓冲区。

也就是说,你对它进行了 malloc,然后释放了它。

在退出之前,您可以自己关闭流,从而释放缓冲区。或者,您可以刷新流并setvbuf使用缓冲区参数再次调用NULL以切换回库管理的缓冲区或无缓冲的 I/O。

  • 标准不允许使用 NULL 缓冲区参数再次调用“setvbuf”(请参阅​​我的答案中的引用)。 (3认同)