EOF是否设置错误?

时间:2014-03-24 05:43:13

标签: c unix system-calls

我总是在努力处理系统调用的返回值 - 它们只是如此不一致! 通常我会检查它们是否为NULL或-1,然后调用perror。但是,对于fgets,手册页说:

  

gets()fgets()成功返回,NULL出错,或者文件结束时没有读取任何字符。

表示返回值NULL不一定是错误 - 它也可以是EOF。到达文件末尾时是否设置了错误?在这种情况下我还可以拨打perror吗?

如果没有,告诉调用是否返回错误与EOF的常见方法是什么。我希望perror使用NULL字符串表示错误,并使用自定义字符串表示EOF。

2 个答案:

答案 0 :(得分:6)

使用ferrorfeof区分错误和EOF。没有一般方法可以确切地找出错误是什么,如果有错误,但你可以告诉它有错误。

标准C (f)gets(和(f)getc)不需要设置errno,尽管符合标准的库实现可以将errno设置为非零值将。

Posix确实要求(f)get{c,s}设置errno读取错误,但这只会在您确定存在读取错误(通过调用ferror)后帮助您。同样重要的是要记住库函数永远不会将errno设置为0,但即使没有错误发生,也可以将errno设置为非零值。因此,您无法测试errno作为检查任何库函数(包括fgets)的错误返回的替代。由于文件结尾是一个错误,errno将(可能)不会在EOF上修改,因此在这种情况下它的值是没有意义的。

答案 1 :(得分:1)

根据fputs自己的文档,是的,EOF确实设置了errno。手册间接地推断它,而不是直接说明它,希望将被修改。函数fputs返回一个整数,该函数在成功时为正,在失败时为EOF。因此,错误处理fput的关键是设置一个代码块,用于检查fput被调用时的返回值。以下是我如何被教导处理fputs错误的片段。

if (fputs(buffer, stdout) == EOF)
{
  fprintf(stderr, "fputs returned EOF: %s\n", strerror(errno));
  // .. and now do whatever cleanup you need to do.
  // or be lazy and exit(-1)
}

这里我将缓冲区的内容写入标准输出并检查fputs是否返回EOF。 EOF表示设置了错误代码,因此只要您按照fput手册页上的文档进行操作,就应该能够创建一堆if语句来检查errno可以设置的各种错误代码。

(1)什么是缓冲?我在其他地方声明了一些字符数组。

(2)fprintf做什么?它将输出打印到传入的文件描述符,在这种情况下是标准错误(stderr ...它打印到控制台,如stdout,但是出错)。

(3)什么是strerror?它是string.h头文件中定义的函数,它打印传入的错误代码的错误信息。它包含可以设置为errno的每个错误代码的信息。标题string.h不应该与strings.h混淆,strings.h是一个不包含strerror的BSD linux头文件(3)。

编辑:好的,我搞砸了。你正在寻找关于fgets而不是fputs的答案。

要检查fgets上的错误,请执行以下操作

if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{ 
  // your file isn't readable. Check permissions
  fprintf(stderr, "fgets error occurred: %s\n," strerror(errno));
  // do cleanup
}
// special: you also need to check errno AFTER the if statement...

问题是,你在这方面遇到错误的唯一方法是流变得不可读,这可能是由于权限或尝试读取处于写入模式的内容。对于网络,可能会在读取过程中切断连接,在这种情况下,您还需要在fgets if语句后检查错误代码。但如果出现问题,它会设置错误代码。

至少是手册页是否正确。有关更多详细信息,请参见linux手册页。只有可以设置的错误代码是“我无法读取此东西”代码,即errno == EBADF