如何处理c中的错误返回

时间:2009-12-08 07:34:19

标签: c

当函数调用深入时,如何处理C中例程的错误返回?

由于C不提供异常抛出机制,我们必须检查每个函数的返回值。例如,“a”例程可以被“b”调用,“b”可以被许多其他例程调用,所以如果“a”返回错误,那么我们必须在“b”和所有其他例程中检查它叫“b”。

如果“a”是一个非常基本的例程,它可能会使代码变得复杂。有这样的问题的解决方案吗? 实际上,在这里我希望得到一个快速的返回路径,如果发生这样的错误,所以我们只需要在一个地方处理这个错误。

9 个答案:

答案 0 :(得分:5)

您可以使用setjmp()和longjmp()来模拟C中的异常。

http://en.wikipedia.org/wiki/Setjmp.h

答案 1 :(得分:4)

有几种策略,但我认为最有用的是每个函数在成功时返回零,在非零时返回错误,其中特定值表示特定错误。

这与早期返回逻辑相结合实际上使函数非常容易阅读:

int
func (int param)
{
    int rc;
    rc = func2 (param);
    if (rc)
        return rc;

    rc = func3 (param);
    if (rc)
        return rc;

    // do something else
    return 0;
}

答案 2 :(得分:3)

我担心的是它的样子。没有例外,您必须检查调用链中每个函数的返回值。

答案 3 :(得分:3)

在一般情况下,没有。您需要确保您的函数调用按预期工作。返回代码是确保这一点的主要机制(尽管设置全局错误号或错误标志也可能是合适的,具体取决于上下文 - 而不是它简化了很多事情。)

采用其他人建议的技术之一,可以让您的错误检查统一,更易于阅读。这将有助于保持可维护性。

对于某些基本功能,失败的几率可能足够低,不会打扰,例如

int sum(int a, int b) {
  return a + b;
}

确实不需要检查。但是系统调用创建一个新窗口应该是真的。

答案 4 :(得分:2)

你制作了一个error_codes列表(我使用了enum)并在你的所有app中使用它们“flat”。 因此,如果b调用a并获取其中一个错误代码,您可以决定是继续使用,还是返回原始错误代码。

用户/程序员应该有一个包含所有错误代码的列表......

答案 5 :(得分:2)

最好的方法是尽可能以不会失败的方式设计功能。如果他们进行I / O或内存分配或其他有副作用的事情,这是不可能的,所以要避免这些。例如,不是使用分配内存和复制字符串的函数,而是使用一个函数来获取预先分配的内存,并将其复制到字符串中。或者你可能只有一个I / O发生的地方,程序的其余部分只是操作内存中的数据。

或者,您可以决定某些类型的错误是否可以杀死该过程。例如,如果你内存不足,很难从中恢复,所以你也可能崩溃。 (但是以一种用户友好的方式做到这一点:连续检查相关数据到磁盘,以便用户可以恢复。)这样,功能可以假装它们永远不会失败。

setjmp建议Murali VP也值得一试。

答案 6 :(得分:1)

AFAIK C是一种结构编程语言。

如果这是问题,同样适用于RTL函数,如fopen,fscanf等......

所以我想传播错误会更好。

答案 7 :(得分:1)

您可以使用宏。

#define FAIL_FUNC( funcname, ... )    if ( !funcname( _VA_ARGS_ )  ) \
                                           return false;

这样您可以维护相同的系统,但不必每次都编写相同的代码......

答案 8 :(得分:1)

您可以使用丑陋的if金字塔,例如:

if (getting resource 1 succeeds) {
    if (getting resource 2 succeeds) {
        if (getting resource 3 succeeds) {
            do something;
            return success;
        }
        free resource 2;
    }
    free resource 1;
}
return failure;

或等同于goto(看起来更好):

if (getting resource 1 failed) goto err1;
if (getting resource 2 failed) goto err2;
if (getting resource 3 failed) goto err3;
do something;
return success;

err3:
free resource 2;
err2:
free resource 1;
err1:
return failure;