【问题标题】:Null-termination guarantees by fgets if NULL is returned如果返回 NULL,则 fgets 的 Null 终止保证
【发布时间】:2016-03-08 22:03:06
【问题描述】:

在阅读 C99 草案 ISO/IEC 9899:TC2 WG14/N1124 时,我偶然发现了一些令我担心的陈述:

如果fgets 返回NULL,给fgets 的字符串/缓冲区是否也保证为空终止?

§7.19.7.2 说明中的状态

一个 在读入数组的最后一个字符之后立即写入空字符。

但正在退货中:

如果在操作过程中发生读取错误,则数组内容为 不确定并返回一个空指针。

因此,在我的解释中,最后一条语句暗示在任何NULL-returning 情况下都没有给出这种保证。 我已经要纠正http://en.cppreference.com,因为他们使用的是errnofgets 没有义务设置。但我不确定我是否误解了这一点。

【问题讨论】:

  • 我知道在返回 NULL 的情况下无法验证缓冲区是否以 null 结尾。如果有任何疑问,不要指望有那个方便的尾随零。 ;-)
  • 既然数组中没有读入字符,那后面怎么写null字符呢?
  • 我已经要改正了……”为什么,什么?
  • "如果在操作过程中发生读取错误,则数组内容不确定,返回空指针。"对我来说听起来很清楚。缓冲区的内容是 indeterminate 周期。
  • 也许我应该把这个问题作为一个维基问题来问?!我希望有人可以发布带有更多参考的答案,以防止这种可能的误解。

标签: c stdio


【解决方案1】:

您正确地解释了标准。如果出现错误,函数将返回 NULL,并且缓冲区的内容不可信。

这允许fgets 直接读入目标缓冲区,中间没有任何双缓冲区。因此,在预期数据中途出错时,它可能会简单地停止并返回 NULL。

还要注意这种特殊情况(7.21.7.2):

如果遇到文件结尾并且没有字符被读入 数组,数组的内容保持不变并且为空 返回指针。

【讨论】:

  • 所以如果缓冲区之前是空终止的,它会保持这种状态,如果feof 也返回非零值? (抱歉,在您发布答案的那一刻,我已经编辑了我的问题)
  • @Superlokkus 如果在调用fgets 之前使用feof 检查流并且fgets 遇到错误,则缓冲区的内容是不确定的。想象一下这种情况:您的缓冲区包含文本“hi”,即 3 个字符:{'h','i','\0'},后跟任何随机垃圾。然后您告诉 fgets 读取 10 个字符并覆盖缓冲区,但在 5 个字符之后出现错误。此时缓冲区可能包含类似{'a','b','c','d','e', <garbage> } 的内容。 \0 已被覆盖。 Indeterminate 意味着数据已经变成垃圾,不应该被使用。
  • 好的,但我想如果某些附加条件为真,它仍然会以 null 终止,例如 最后一个字符至少已经是 \0 或者 fgets 的计数是 > = 比以前的时间等。但我想许多先决条件只会把你的答案和我的问题弄得一团糟。
  • @Superlokkus Indeterminate value 意味着如果您尝试将值用于任何目的,则会调用未定义的行为。所以一旦出错,fgets 也可以将字符串 "nonsense" 写入缓冲区,然后返回 NULL,就 C 标准而言,它仍然严格符合。
  • 为了完整起见,您可能会感兴趣的是3rd reason fgets() 可能会返回NULL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多