繁体   English   中英

谁免费的setvbuf缓冲区?

[英]who free's setvbuf buffer?

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

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

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

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

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

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

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

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

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

setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");

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

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

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

也可以从手册页 (至少在我的系统上):

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

也就是说,你将它解决了,你释放了它。

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

至少根据C标准,不允许你的最后一个场景:“setvbuf函数只有在stream指向的流与打开的文件相关联之后和任何其他操作之前(除了不成功的调用之外)才可以使用to setvbuf)在流上执行。“ (C99,§7.19.5.6/ 2)。

至于何时在更简单的情况下释放内存,在途中是调用atexit()来注册一个回调,该回调将在退出main()之后释放内存,但是在将控制权返回给OS之前。

您可以显式关闭stdinstdoutstderr (使用fclose() )。

对于大多数操作系统,堆内存在程序退出时自动释放。 因此,没有未释放的缓冲区没有实际问题(存在一个外观问题,即那些未发布的缓冲区会污染Valgrind的输出)。 如果你觉得在标准输入或输出上调用setvbuf()的冲动,我的建议是使用静态缓冲区。 静态缓冲区不需要分配或释放,并且在这里是合适的,因为只有三个标准流,并且您担心这些流在程序终止时保持打开的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM