2017-01-26 33 views
2

Apple developer documentation状态:fgets的n参数的含义是否随时间而改变?

fgets安全注意:虽然fgets功能提供了读取数据的数量有限的能力,就必须使用时要小心。像“更安全”列中的其他功能一样,fgets始终终止字符串。但是,与该列中的其他函数不同,它需要读取的最大字节数,而不是缓冲区大小。

最后一句对我来说听起来不对。为了比较,这里是what POSIX says

fgets()功能必须从阅读流字节到阵列指向s直到n-1字节被读入,或<newline>被读出并传送到s,或最终OF-文件条件遇到。在读入数组的最后一个字节之后立即写入空字节。

这里是an ISO C draft from 2005 says

fgets函数读取比n从流中指定的字符数少至多一个指向stream到阵列通过s指向。换行符(保留)或文件结束后不会读取其他字符。在读入数组的最后一个字符后立即写入空字符。

FreeBSD的手册页说一样的C标准和POSIX。

这让我觉得苹果文档显然是错误的。最简单的解释是,苹果公司在发表这篇文章时并不知情。但虽然很简单,但这个假设对我来说并不合理。

苹果是否有其他原因可能偏离C标准的措辞?

+2

该文件是错误的。手册页是正确的。 – user3386109

+0

更准确地说:文档不对或者'fgets'实现不符合。我猜这是前者。 –

+0

POSIX似乎很清楚:“直到读取n-1个字节” –

回答

1

fgets功能最多大小减去文件一个字节读取。如果将错误值作为缓冲区大小传递,那么fgets可能会写出越界。

因此,您显示的Apple文档的引用是正确的,因为该值与从文件中读取的字节数更相关。但另一方面,任何正常的代码在使用fgets时会使用实际的缓冲区大小。如果该号码是从用户输入的,那么在使用之前应该对其进行验证。

在另一方面文档继续状态

在实际条款(注桑德德Dycker感谢),这意味着你必须总是传递一个大小值比规模少一个为空终止留下空间的缓冲区。如果你不这样做,fgets函数将尽职地终止字符串,超过缓冲区的末尾,可能会覆盖随后的任何字节数据。

这个是错误的。传递给fgets的大小参数始终包含字符串终止符。至少根据C标准。

+0

这并不能真正回答我的问题。你的参考不像我在我的问题中给出的两个规范那样规范,我认为它甚至包含错误的信息。我的问题是关于_why_ Apple可能发布了这个错误信息。 –

2

即使早期(1970年代早期)版本的fgets()指定n是缓冲区的大小,并且所述缓冲器将与'\0'被终止。

Kernighan和Ritchie在他们的所有书籍和文档中都正确地反映了这一点。然而,一些介绍性文本的作者(我不会尝试命名,因为我敢肯定我会错过一些,并且所有人都应该同样尴尬),它记录了最多可以是n的字符写入缓冲区,并且尾部'\0'可能在某些情况下被丢弃。

+0

我只知道一个作者会写这样的废话,事实上,他的书中有错误。 :)很高兴知道他不是唯一一个。 –

相关问题