【问题标题】:c - read() and fread() return valuesc - read() 和 fread() 返回值
【发布时间】:2020-08-27 18:04:56
【问题描述】:

SO的好人!

我有一个理论问题。 在read() 联机帮助页中,我阅读了以下内容:

   On error, -1 is returned, and errno is set appropriately.  In this
   case, it is left unspecified whether the file position (if any)
   changes.

而在fread() 中对应的片段如下:

   If an error occurs, or the end of the file is
   reached, the return value is a short item count (or zero).
   ...
   **fread()** does not distinguish between end-of-file and error, and
   callers must use feof(3) and ferror(3) to determine which occurred.

我的问题 - read() 区分 EOF 和错误,而 fread() 不区分,有什么实际原因吗?

提前谢谢你!

【问题讨论】:

  • 接口在不同时期演变,可能由不同的实现者演变。
  • @tadman - 我仍然习惯于标准库可能会因为“只是因为”而不是某些策划者的计划而出现问题。
  • 其中许多都是当时有意义的设计决策。当 C 在 1972 年问世时,计算机的资源极其有限,例如 千字节 的内存被认为是奢侈的,而 兆字节 的内存仍然遥不可及。随着后来的计算机增加了更多功能,通过fread 进行缓冲读取之类的事情变得有意义,但这是在read 已经建立之后很久。
  • 我认为 Barmar 对“为什么”的技术细节有很好的解释,但在更一般的层面上,您需要记住,并非每个功能都能按预期工作具有千兆字节内存和千兆赫速度 CPU 的现代计算机。在千字节和千赫兹的时代,您必须非常高效。在fread() 的情况下,与许多事情一样,如果您想了解更多信息,您必须询问。做从未使用过的额外工作真的很浪费,必须避免。
  • @tadman - 是的,从技术角度来看,现在很清楚了。我想在更一般的层面上,它只是可以接受的东西。感谢您的回答!

标签: c io fread


【解决方案1】:

fread 的返回值为size_t。这是一个无符号类型,因此没有可用的值与指示读取了多少项的值不同。

此外,fread() 可能需要多次调用read() 才能读取所有请求的项目。如果在后面的一次读取中发生错误或 EOF,它仍应返回之前成功读取的所有项目。所以它会返回该项目计数。

由于无法在返回值中编码短项计数的原因,因此需要有一些其他方式来返回它。使用feof()ferror() 将其留给调用者更容易。

如果read() 在部分读取后遇到错误,这通常被视为成功。它返回读取的数据的长度。调用者直到 next 调用read() 时才发现错误,当它返回-1 并设置errno

信号也可能导致read() 提前返回。在这种情况下,它返回-1 并设置errno == EINTR。内核将部分读取保存在缓冲区中,以便在下次调用时返回。

【讨论】:

  • 但是如果发生错误,为什么read() 不返回成功读取的字节数?我的意思是,我明白这是对系统的基本单次调用,但如果read() 不这样做,为什么fread() 应该这样做?它在实践中是否更有用?
  • 因为除了返回负值之外,它没有任何报错方式。
  • @AntonTretyakov:虽然实现处理错误的方式有很大的灵活性,但原则上它确实read 可以返回短读,其原因之一是在部分读已发生后无法继续。例如,对于文件结束条件和EINTR(如果您安装了中断信号处理程序),这是强制性的,但我认为这将是所有错误的首选行为,并且大多数实现可能都是这样做的。毕竟,当您尝试继续时,您会看到无法继续的原因。
  • @R..GitHubSTOPHELPINGICE 谢谢,我已经更新了答案以解释我对这些情况的理解。
  • 在已经传输数据后,读取不会因 EINTR 而失败。然后转移的金额将丢失。取而代之的是,它成功 只是读了一小会。只有在没有数据传输时才会发生 EINTR。
猜你喜欢
  • 2012-05-06
  • 2019-03-24
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 2013-02-07
相关资源
最近更新 更多