简体   繁体   English

EOF 是否设置错误号?

[英]Does EOF set errno?

I always struggle with return values of system calls - they are just so inconsistent!我总是为系统调用的返回值而苦恼——它们太不一致了! Normally I check if they are NULL or -1 and then call perror .通常我检查它们是 NULL 还是 -1 然后调用perror However, for fgets , the man page says:但是,对于fgets ,手册页说:

gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read. gets()fgets()在成功时返回 s,在错误时返回NULL ,或者在没有读取任何字符的情况下出现文件结尾。

which means the return value NULL is not necessarily an error - it can also be EOF.这意味着返回值NULL不一定是错误 - 它也可以是 EOF。 Is errno set when the end of file is reached?到达文件末尾时是否设置了 errno? Can I still call perror in this case?在这种情况下,我还可以调用perror吗?

If not, what is the common way to tell if the call returned an error versus EOF.如果没有,判断调用是否返回错误与 EOF 的常用方法是什么。 I want to use perror with NULL string for errors and a custom string for EOF.我想将perror与 NULL 字符串一起用于错误,并为 EOF 使用自定义字符串。

Use ferror and feof to distinguish between error and EOF.使用ferrorfeof来区分 error 和 EOF。 There's no general way to find out exactly what the error was, if there was an error, but you can tell that there was one.没有通用的方法可以准确找出错误是什么,如果有错误,但你可以知道有错误。

Standard C (f)gets (and (f)getc ) are not required to set errno , although a conforming library implementation can set errno to a non-zero value pretty much at will.标准 C (f)gets (和(f)getc ) 不需要设置errno ,尽管符合标准的库实现可以随意将errno为非零值。

Posix does requires that (f)get{c,s} set errno on read errors, but that only helps you after you have determined that there was a read error (by calling ferror ). Posix 确实要求(f)get{c,s}在读取错误时设置errno ,但这只会在您确定存在读取错误(通过调用ferror )后对您有所帮助。 It's also important to remember that library functions never set errno to 0, but may set errno to a non-zero value even if no error occurs.同样重要的是要记住,库函数从不将errno为 0,但即使没有发生错误,也可能将errno为非零值。 So you cannot test errno as a replacement for checking the error return of any library function, including fgets .所以你不能测试errno作为检查任何库函数的错误返回的替代,包括fgets And since end-of-file is not an error, errno will (probably) not be modified on EOF, so its value in that case is meaningless.并且由于文件结尾不是错误,因此errno不会(可能)在 EOF 上被修改,因此在这种情况下它的值是没有意义的。

According to fputs own documentation, yes, EOF does set errno.根据 fputs 自己的文档,是的,EOF 确实设置了 errno。 The man pages infer it indirectly as opposed to stating it outright, which hopefully will be amended.手册页间接推断它而不是直接说明它,希望将对其进行修改。 The function fputs returns an integer that will either be positive on success or EOF on failure.函数 fputs 返回一个整数,成功时为正数,失败时为 EOF。 So the key to error handling fputs is to setup a code block that checks the return value of fputs as it is being called.因此,错误处理 fputs 的关键是设置一个代码块,在调用 fputs 时检查它的返回值。 The following is a snippet of how I've been taught to handle fputs errors.以下是我被教导如何处理 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)
}

Here I am writing the contents of buffer to standard output and checking to see if fputs returns EOF.在这里,我将缓冲区的内容写入标准输出并检查 fputs 是否返回 EOF。 EOF indicates an error code was set, so as long as you follow the documentation on the man pages for fputs, you should be able to create a bunch of if statements to check the various error codes errno can be set to. EOF 表示设置了错误代码,因此只要您遵循 fputs 手册页上的文档,您应该能够创建一堆 if 语句来检查 errno 可以设置为的各种错误代码。

(1) What is buffer? (1) 什么是缓冲? Some character array I declared elsewhere.我在别处声明的一些字符数组。

(2) What does fprintf do? (2) fprintf 有什么作用? It prints output to a passed in file descriptor, which is in this case standard error (stderr... it prints to console like stdout, but for errors).它将输出打印到传入的文件描述符,在这种情况下是标准错误(stderr ...它像 stdout 一样打印到控制台,但有错误)。

(3) What is strerror? (3)什么是strerror? It is a function defined in the string.h header that prints error information for the passed in error code.它是在 string.h 头文件中定义的一个函数,用于为传入的错误代码打印错误信息。 It has information for every single error code that errno can be set to.它具有 errno 可以设置的每个错误代码的信息。 The header string.h should NOT be confused with strings.h, which is a BSD linux header file that does not contain strerror(3).头文件string.h 不应与strings.h 混淆,后者是一个不包含strerror(3) 的BSD linux 头文件。

Edit: Ok, I messed up.编辑:好的,我搞砸了。 You were looking for an answer on fgets, not fputs.您正在寻找关于 fgets 的答案,而不是 fputs。

To check for an error on fgets, do the following要检查 fgets 上的错误,请执行以下操作

if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{ 
  // print out error as a string to stderr
  fprintf(stderr, "fgets error occurred: %s\n", strerror(errno));
  // do cleanup
}
// special: you also need to check errno AFTER the if statement...

The thing is, the only way you are getting an error on this is if the stream becomes unreadable, which is either due to permissions or trying to read something that is in write mode.问题是,您在此方面遇到错误的唯一方法是流变得不可读,这要么是由于权限所致,要么是尝试读取处于写入模式的内容。 In the case of a network, it may be possible for something to cut off your connection in the middle of reading, in which case you need to check the error code after the fgets if statement as well.在网络的情况下,可能会在读取过程中切断您的连接,在这种情况下,您还需要检查 fgets if 语句之后的错误代码。 But it will set the error code if something went wrong.但如果出现问题,它会设置错误代码。

At least that is if the man pages are correct.至少如果手册页是正确的。 See the linux man pages for more details.有关更多详细信息,请参阅 linux 手册页。 Only error code that can be set is the "I can't read this thing" code, which is errno == EBADF唯一可以设置的错误码是“I can't read this thing”码,即errno == EBADF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM