问题 C检查标准库中的错误(ret


我经常看到代码通过测试小于零而不是显式定义来检查POSIX函数的错误,并且通常只使用错误代码-1。那是

ret = function();
if (ret < 0) {
    ...
}

VS

ret = function();
if (ret == -1) {
    ...
}

第一次练习有什么目的吗?在某些体系结构上比0与-1比较的速度要快吗?如果现在定义的唯一错误代码是-1,那么C或POSIX标准是否可以保证第一个替代方案将来不会中断?如果没有,是否应该被视为不良做法? (我想大多数函数不太可能以这种方式改变,导致很多已编写的代码破坏?)。

编辑:使问题更清楚:我只讨论专门返回-1的函数作为标准定义的错误代码。我知道有一些没有。我在很多地方看到了<0检查这些函数而不是== -1。因此这个问题。


8125
2018-02-10 17:44


起源

我看到一些关于某些函数返回其他负值(不仅仅是-1)这一事实的评论,但我看到你已经明确表示你不是在谈论那些。你有一些现有代码的例子,有人这样做了吗?你可以从一个特定的例子得到更积极的回应,你可以说“函数X被定义为在出错时返回-1;为什么作者不写 ret == -1 而不是 ret < 0?” - Joshua Taylor


答案:


这主要是历史事故。曾经有(pre-POSIX)类UNIX系统在错误时返回-errno而不是-1,因此您不必使用全局errno变量。因此检查<0将适用于此类系统。

您仍然可以在Linux中看到此历史记录 - 系统调用返回-errno,C库检查范围[-4096 ..- 1]中的值。如果返回值在该范围内,则库将其否定并将其存储在errno(内核不知道)中,然后返回-1。


7
2018-02-10 18:17





首先,一些函数只有一个错误代码,有些函数有更多。举个例子, pthread_create 是一个POSIX函数,可以返回多个错误代码。当我不关心特定的错误代码时,我也不想关心它们有多少。在这种情况下,检查负回报只是一种可靠的通用无维护方法,涵盖所有情况。另外,POSIX规范中的错误通常根据清单常数来描述,而不是根据特定数值来描述。

其次,我不确定POSIX究竟对于现有函数的错误返回的可扩展性是什么,但我自然希望在我的代码中预期这种可能性。

第三,通常,在许多(如果不是大多数或所有)处理器上检查“否定”值比检查特定值更有效。许多CPU都有一个专用的CPU状态标志,用于指示否定结果。这意味着对负值的测试不必涉及文字操作数。例如,在x86平台上测试否定性不必涉及与文字的比较 0。与...比较 具体 值通常需要将特定值嵌入到机器指令中,从而导致指令变慢。但是,无论如何“特殊”的价值观,如 0-11 等,可以使用更聪明有效的技术进行测试。因此,我怀疑为了性能原因,这种比较是以这种方式完成的。


8
2018-02-10 17:49



我说'通常'。我没有概括关于所有函数的问题,这些函数在出错时仅返回-1。也许应该让它更清楚。感谢你的回答。 - user2079392


如果定义函数返回 -1 关于错误和 0 成功,然后使用 -1 测试错误和 0 测试成功。

做其他事情是不准确的,并增加了发生故障的可能性。

如果一个人想要真正处于保存方面,那么应该尝试检测函数返回未定义为返回值的值的所有情况,并在此情况下执行addtional断言。对于我的介绍示例,这将是所有值 >0 和 <-1

而已。

int func(void); /* Returns 0 on success and -1 on error. */

int main(void)
{
  int result = func();

  switch result
  {
    case 0:
      /* Success. */
      break;

    case -1:
      /* Failure. */
      break;

    default:
      /* Unexpected result! */
      break;
   }

   return 0;
}

1
2018-02-10 18:12