4

我正在看一段 C 代码,它是

void printerror(char *message)
{
    printf ("There was an error: '%s'\n", message);
    switch (errno) {
       ... do stuff depending on errno
    }
}

我认为这可能是一个问题,因为 printf 可能会在进入函数和到达switch. 但是,printf 的手册页没有说明它设置 errno,所以我可以假设它永远不会设置它吗?标准中是否有任何内容可以保证哪些函数将使用和不会使用 errno?

4

3 回答 3

10

任何函数都可以设置 errno,但前提是它将其设置为非零值。ANSI C 规范规定:

errno 的值在程序启动时为零,但绝不会被任何库函数设置为零。* errno 的值可以由库函数调用设置为非零,无论是否存在错误,只要使用 errno未记录在标准中的功能描述中。

*因此,使用 errno 进行错误检查的程序应在库函数调用之前将其设置为零,然后在后续库函数调用之前对其进行检查。

因此,如果您使用 errno,最佳实践方法是在可能会失败的库调用之前立即将值设置为 0,然后立即读取它。在上述情况下,添加以下内容就足够了:

int localErrno = errno

在 printf 语句之前并使用 localErrno 进行切换。当然,这假设在失败的函数和您对 printerror 的调用之间没有库调用。如果有,您需要在调用失败后存储 errno 并将其传递给您的 printerror 函数。

于 2010-12-08T19:01:09.997 回答
4

在极少数情况下,printf 可以设置 errno。如果您将程序中的标准输出重定向到文件并且文件系统已满,printf() 将返回一个负数并将 errno 设置为 ENOSPC(设备上没有剩余空间)。在调用 printf() 之前,您应该制作 errno 的本地副本。

于 2010-12-08T20:23:34.573 回答
3

The C99 standard specifies the following:

The value of errno is zero at program startup, but is never set to zero by any library function. The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

So, in short, errno may be set by any library function. In order to determine if it actually is in a given case, standard practice is to set it to zero before calling the function in question.

于 2010-12-08T18:52:39.100 回答