是否要避免连续调用`errno`?

时间:2010-10-06 07:42:33

标签: c

处理相同错误时多次调用errno是否安全。或者使用本地副本更安全吗?

此示例说明了我的问题:

// If recvfrom() fails it returns -1 and sets errno to indicate the error.
int res = recvfrom(...);
if (res < 0)
{
    // Risky?
    printf("Error code: %d. Error message: %s\n", errno, strerror(errno));

    // Safer alternative?
    int errorNumber = errno;
    printf("Error code: %d. Error message: %s\n", errorNumber, strerror(errorNumber));
}

5 个答案:

答案 0 :(得分:5)

  

只有在调用明确声明要设置的函数之后,才能定义errno的值,直到它被下一个函数调用更改或者应用程序为其赋值。

http://www.opengroup.org/onlinepubs/009695399/functions/errno.html

然而,即使strerror理论上也可以算作可以改变它的函数调用(请参阅schot的评论),所以从理论上讲,你应该使用保存优先形式。

答案 1 :(得分:2)

包括printf和strerror在内的任何标准库函数都允许更改errno,即使实际上没有错误发生:

  

7.5 3程序启动时errno的值为零,但永远不会设置为   任何库函数都为零。 170)   errno的值可以设置为   由函数调用非零   是否有错误,   如果没有使用errno   记录在描述中   这个国际的功能   标准。

答案 2 :(得分:1)

errno是可变的而不是功能。使用它时,无法重置。因此,可以使用errno次数,假设您没有调用任何可以更改/重置errno的函数。

答案 3 :(得分:1)

现在通常errno比变量复杂得多:

  

... errno扩展为a   可修改的左值,类型为int,   其值设置为a   几个正误差数   库函数。它没有具体说明   errno是一个宏还是一个   用外部声明的标识符   连锁。如果是宏定义   为了访问而被压制   实际对象,或程序定义   名称为errno的标识符   行为未定义。

E.g。在POSIX中,它保证评估为特定于当前线程的东西。因此,它的访问成本可能高于简单变量。

所以是的,如果性能是一个问题,我会选择本地副本,尽管我从来没有真正想过这个。

答案 4 :(得分:0)

我自己只是在研究这个问题,我认为另一个功能可能更适合这个问题,perror。 perror非常简单,例如,如果你对某些内存进行malloc并且你想要一些有意义的错误消息,那么当malloc失败时,strerror会提供这些消息:

char **str_array = (char**) malloc(SOME_CONSTANT * sizeof(char*));
if (str_array == NULL){
    perror("malloc failed on str_array");
}

perror打印您键入的字符串,添加空格,然后添加分号,然后打印人类可读的错误文本。它似乎也没有strerror所带来的副作用,除非我正确地解释了手册页,因为它没有错误的部分:http://man7.org/linux/man-pages/man3/perror.3.html

我也在进行可能失败的连续调用,而perror似乎更少的代码行和更好的语法。但是,我比C更新,所以如果这些信息不准确,请编辑或删除。