【发布时间】:2020-05-23 13:45:14
【问题描述】:
在尝试implement freopen() 时,我在标准中提出了一条规范,据我所知,该规范实际上并未指定任何内容。
所以...freopen() 将关闭流(忽略错误),清除其错误和 EOF 标志,重置宽方向,然后以给定模式重新打开流。这很清楚;这基本上是一个 fclose() / fopen()。即使没有这样定义,也很明显这是预期的结果。
但是,关于 setvbuf() 可能对流所做的事情,我有两个问题 - 设置用户分配的缓冲区和/或更改缓冲区策略。
问题 1。
1) freopen() 是否期望将事物恢复到默认状态,就好像它实际上调用了 fopen()?或者,无论用户通过setvbuf() 在旧流上设置什么,它是否有望延续到新流?这指的是缓冲内存和缓冲策略,但这里的主要问题是缓冲内存。
fclose() 的规范指定用户通过setvbuf() 与流关联的任何缓冲区都被解除关联,即现在可以由用户free()'d。
但freopen() 仅指定它关闭与流关联的文件,而不是fclose()es 它。
那么,freopen() 之后,用户关联的缓冲内存是否仍然与流关联?
问题 2。
freopen() 可以用于FILE 结构,该结构在调用时实际上与打开的文件无关(因为尝试关闭文件的错误将被忽略)。
该文件结构可能是以前打开的流,具有用户分配的缓冲内存和缓冲策略。 freopen() 是为了遵守这些设置,即将缓冲存储器/策略与“重新”打开的文件重新关联,还是将结构重新初始化为默认值,假设用户 free()d 在 @987654337 之后使用缓冲存储器之前 @ing 文件?
我的看法。
看看 Q2,我看不到标准库有办法可靠地确定具有用户分配的缓冲内存的当前未打开的 FILE 结构是否仍然“拥有”该缓冲内存,或者用户是否已经收回了那段记忆。 (可以想象,该内存可能是本地的,即不是malloc() / free() 处理的内存列表的一部分,即使我愿意去那里——这将是标准库函数所期望的非常反常的工作。)
缓冲区政策的类似考虑因素。
因此,据我所知,唯一可靠的处理方式是freopen() 将“与指定流关联的任何文件”作为“真实”fclose(),并将缓冲内存/策略重新设置为默认值。
我的理解是否正确,或者 Q1 / Q2 有其他答案吗?
【问题讨论】:
-
freopen 为新的流返回一个新的 FILE*。作为参数传递的 FILE* 已关闭。复制缓冲区设置是出乎意料的。
-
@stark:根据定义,如果出现错误,返回的
FILE *要么是NULL,要么是作为参数传递给函数的FILE *( “......流的价值”)。所以不幸的是,它并没有那么明确。 -
重用存储是明显的优化,但是函数的描述是新的流。
-
@stark:我不同意“明显”和“新流”。 (标准的措辞支持我。)如果这是您的答案,请发布它,但作为评论,这没有帮助。 (评论应该是为了澄清问题,而不是试图回答它。)
-
感谢您完成这项工作...我将尝试并做出贡献,并为同一目标投入了一些时间。你在
FILE结构中添加了一个filename槽来实现freopen(NULL, mode, stream)的有问题的规范:我怀疑这既没有必要也不够,而且你在实现中有一个愚蠢的错误:stream->filename = (char *)malloc( strlen( filename ) )。一定要使用strdup(),它终于进入了下一个 C 标准。
标签: c language-lawyer standards standard-library c-standard-library