当函数调用深入时,如何处理C中例程的错误返回?
由于C不提供异常抛出机制,我们必须检查每个函数的返回值。例如,“a”例程可以被“b”调用,“b”可以被许多其他例程调用,所以如果“a”返回错误,那么我们必须在“b”和所有其他例程中检查它叫“b”。
如果“a”是一个非常基本的例程,它可能会使代码变得复杂。有这样的问题的解决方案吗? 实际上,在这里我希望得到一个快速的返回路径,如果发生这样的错误,所以我们只需要在一个地方处理这个错误。
答案 0 :(得分:5)
您可以使用setjmp()和longjmp()来模拟C中的异常。
答案 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;