2010-10-06 59 views
7

在处理相同的错误时多次调用errno是否安全?或者使用本地副本更安全?是否连续调用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)); 
} 
+1

+1有趣的问题证明有一个不平凡的答案和可能的实际后果。 – 2010-10-06 08:39:36

回答

5

errno的值应仅在一个函数的调用,这就是它明确规定要设置的,直到它被下一个改变来定义函数调用或应用程序为其分配值。

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

然而,即使strerror理论上可以算作一个函数调用,可以改变它(见散粒评论),所以你应该,在理论上,还是与保存,第一种形式去。

+1

但是,printf可能会导致对errno的更改。 http://linux.die.net/man/3/errno(我相信它来自Linux)的手册页警告不要在printf中使用它。但是,对于您的具体情况,这不是问题 - 在调用printf之前,编译器将评估“errno”和“strerror(errno)”。 – Habbie 2010-10-06 07:49:01

+1

但是对'strerror'的调用可能会改变'errno'。虽然我不认为有足够的执行愚蠢/邪恶来做到这一点。 (除了可能是一个DeathStation 9000)。 – schot 2010-10-06 08:03:52

+0

确实如此,编译器可能会在评估errno之前决定评估strerror(errno)。我正在更新我的答案。 – Habbie 2010-10-06 08:07:16

1

errno是可变的,而不是功能。你使用它,它不能被重置。因此,假设您不调用任何可以更改/重置errno的函数,则可以使用errno次数。

+1

'errno'不是一个变量。 – 2010-10-06 11:16:40

2

任何标准库函数包括printf和字符串错误被允许改变错误号,即使发生实际上没有错误:

7.5 3错误号的值是在程序启动时为零,但永远不会设置为 零任意库函数。 170) errno的值可以由一个库函数调用 是否有错误被设置为 非零, 提供使用errno的在 功能的本国际 标准说明不 记载。

+1

切线相关:如果没有实际发生溢出,您是否可以在标准中找到禁止'strtol'和家人将'errno'设置为'ERANGE'的语言?标准过程是在调用这些函数之前将'errno'设置为0,并且如果'LONG_MIN'或'LONG_MAX'返回时检查'errno' - 但是如果他们可以毫无理由地将'errno'设置为'ERANGE',标准测试似乎是无效的...... – 2010-10-06 08:44:01

+0

@R ..:如果为特定函数定义了errno的使用,那么7.5之前不允许明确声明其他行为:“前提是描述中没有记录errno的使用的功能“。 – Secure 2010-10-06 08:51:32

+0

哇,它在你的引用就在那里,我错过了... – 2010-10-06 15:07:59

1

一般时下errno东西不是变量要复杂得多:

...错误号它扩展到具有int类型, 其值设置为 一个 修改的左值积极的错误编号由几个 库函数。它是未指定的 errno是宏还是 标识符声明与外部 链接。如果为了访问 实际对象而抑制了宏定义 ,或者程序定义了名称为errno的 标识符,则 行为未定义。

例如,在POSIX中,它保证评估为当前线程特定的内容。因此,它的访问成本可能高于简单变量。

所以是的,如果性能是一个问题,我会去当地的一个副本,但我从来没有真正为此付出过代价。

0

我只是在研究这个我自己,我认为另一个函数可能更适合这个问题,perror。PERROR很简单,例如,如果你的malloc一些内存和你想的那种有意义的错误消息的strerror的规定,如malloc的失败:

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

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

我也在进行连续调用,可能会失败,perror看起来像少了几行代码和更好的语法。但是,我对C更新,所以如果此信息不准确,请编辑或删除。

相关问题