fread和ferror函数不会设置errno值

8
我正在尝试检查fread()何时会引发错误,因此我使用ferror()
chunk = fread(buf, 1, 100, file);
if (ferror(file))
  {
    return errno;
  }

然而,ferror()手册(man 3 ferrorman ferror)表示:

错误
这些函数不应该失败,也不会设置外部变量errno

那么,当文件被读取时,尽管fread()ferror()没有设置errno,我怎样才能知道发生了什么类型的错误?


3
你读过fread(3)吗?它对错误有详细记录的行为! - Basile Starynkevitch
2
是的,它没有提及设置errno的任何内容。 - Mahmoud Mubarak
5
我认为他的意思正是如此。当然,ferror可以告诉你发生了错误,但由于fread没有记录设置errno,因此如果他能够知道错误的具体原因,他如何知道实际的错误是什么,因为errno不会反映触发流错误状态的具体错误条件? - WhozCraig
1
相关:stdio是否总是设置errno? - Martin R
2个回答

11

无法从此处到达目标地点。

fread 不设置 errno(正如您已经发现的那样),因此你实际上无法确定特定错误状态的信息,只知道存在错误。具体错误的性质通常依赖于实现。在 C 标准库中没有可移植的方式来收集它。

对于特定的系统级错误,你可以通过系统调用来解决,但可能会遇到像 IO 缓冲区不良/不存在等问题。在这种情况下,POSIX 有些许帮助。诸如read之类的调用确实设置了errno并具有一组比较详细的可能结果。如果你使用的平台是 POSIX 兼容的,并且代码真的需要知道这些信息,那么这可能是一个选项。

但是在 C 标准库中,你不会找到更多的信息,只会被告知发生了错误。通常情况下,你也不需要更多的信息。


2
POSIX 要求在出错时 fread 设置 errno。根据 POSIX 对于 fread 的文档所述,“否则,如果发生读取错误,则应设置流的错误指示器,并设置 errno 以指示错误。” - David Hammen
@DavidHammen:那段代码片段被标记为 POSIX extension [CX]。不过,我想知道为什么 GNU 没有遵循这个扩展。当 _XOPEN_SOURCE / _POSIX_SOURCE 被定义为适当的值时,它不应该遵循吗? - MestreLion

4
那些函数不使用errno,所以你也不应该使用它。
值得注意的是,你可以通过fread()的返回值判断一切是否顺利。如果fread()的返回值与传递的nmemb参数(在你的情况下为100)不同,则你已经到达了文件末尾或读取文件时发生了错误(来源)。因此,只在这种情况下进行测试:
只需完全放弃使用errno:
chunk = fread(buf, 1, 100, file);
if (chunk != 100) { // If fread() returns a number different to the nmemb parameter, either error or EOF occured
    if (ferror(file))
      {
        printf("Error occured while reading file.");
        return -1; // Or what ever return value you use to indicate an error
      }
}

@BasileStarynkevitch fread在错误或文件结束时有记录的行为。您需要使用ferror()来检查是否出现了错误,或者使用feof()来检查是否到达了文件结尾。 - Magisch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接