所以我一直在深入研究如何实现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)释放它或使用静态缓冲区,正如有些人提到的那样.我问,因为它似乎是一个尴尬的设计决定.