【问题标题】:fread and ferror don't set errnofread 和 ferror 不设置 errno
【发布时间】:2016-10-24 09:03:00
【问题描述】:

我正在尝试检查fread() 何时引发错误,因此我使用ferror()

chunk = fread(buf, 1, 100, file);
if (ferror(file))
  {
    return errno;
  }

但是,ferror() 手册页说:

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

那么,虽然fread()ferror() 没有设置errno,但我如何知道读取文件时发生的错误类型?

【问题讨论】:

  • 你读过fread(3) 吗?它有一个记录在案的错误行为!
  • 是的,它没有提到设置errno的任何内容。
  • @BasileStarynkevitch 我认为他的观点正是如此。当然ferror 可以告诉您发生了错误,但由于fread 没有 记录为设置errno,他怎么知道实际错误是什么,如果他完全可以,因为errno 不会反映点亮流错误状态的具体错误情况?

标签: c fread errno ferror


【解决方案1】:

你不能从这里到达那里。

fread 没有设置errno(如您所见),因此您无法真正确定特定错误状态;只有一个。错误的确切性质通常取决于实现。没有基于 C 标准库的可移植方式来收集它。

对于特定的系统级错误,您可以将其限制为系统调用,可能会遇到诸如 IO 缓冲不佳/不存在等陷阱。 POSIX 可以在某种程度上帮助您。像readdo 这样的调用设置errno 并有一组相当详细的可能结果。如果您正在使用的平台符合 POSIX 标准,并且代码对于了解情况非常重要,那么这可能是您的一个选择。

但是从 C 标准库中,除了被告知发生了错误之外,您不会发现太多。一般来说,你会发现你不需要更多。

【讨论】:

  • POSIX 要求 freaderrno 设置为错误。来自fread 上的 POSIX 文档,“否则,如果发生读取错误,则应设置流的错误指示符,并应设置 errno 以指示错误。”
  • @DavidHammen:sn-p 被标记为 POSIX extension [CX]。不过,我想知道为什么 GNU 不遵循这个扩展。当_XOPEN_SOURCE / _POSIX_SOURCE 用适当的值定义时,不应该这样吗?
【解决方案2】:

那些函数不使用errno,所以你也不应该使用。

值得注意的是,你可以从fread()的返回值判断一切是否顺利。如果fread() 的返回值与传递的nmemb 参数(在您的情况下为100)不同,那么您要么到达文件末尾,要么读取它时出错(source)。所以只在这种情况下测试:

完全放弃使用 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() 用于文件结束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多