第一次检测到错误后返回错误代码
Posted
技术标签:
【中文标题】第一次检测到错误后返回错误代码【英文标题】:Return error code after first detected error 【发布时间】:2018-05-17 06:25:47 【问题描述】:我有一个函数,它进行一些初始化并调用其他函数,每个函数都返回一个错误代码。在第一次检测到这样的错误后,我希望能够从此函数返回:
int error_code = FirstFunction();
if (error_code != 0)
return error_code;
error_code = SecondFunction();
if (error_code != 0)
return error_code;
// etc...
但是,这不仅看起来很麻烦,而且还有多个退货声明,而且出于合规原因,在我公司这是不允许的。
我怎样才能重新排列它,以便只有一个 return 语句,但在第一个错误代码之后仍然停止?我能想到的唯一方法是嵌套 if 语句:
int error_code = FirstFunction();
if (error_code == 0)
error_code = SecondFunction();
if (error_code == 0)
error_code = ThirdFunction();
// etc...
return error_code;
但这很快就会变得不合理。有没有其他方法可以做到这一点?
编辑:在我的程序中,返回码 0 表示成功(OK),非零表示失败/错误(NOT OK)
【问题讨论】:
那么1
你会回来吗?
0 以外的任何值。0 表示没有错误,非零表示错误
发布error_code
的类型。
【参考方案1】:
您不必嵌套所有的函数调用,下面的代码也可以完成这项工作,并且应该符合您的代码编写规则:
error_code = FirstFunction();
if (error_code == 0)
error_code = SecondFunction();
if (error_code == 0)
error_code = ThirdFunction();
// etc...
return error_code;
【讨论】:
【参考方案2】:这是另一种精益方法,可以根据哪个函数失败返回不同的错误代码:
int func(void)
int code;
int error_code = (code = FirstFunction()) ? code :
(code = SecondFunction()) ? code :
(code = ThirdFunction()) ? code : 0;
/* ... */
return error_code;
【讨论】:
【参考方案3】:精益和干净(like this one,但避免不喜欢的goto
s):
int foo(void)
int error_code;
do
if (0 != (error_code = FirstFunction()))
break;
if (0 != (error_code = SecondFunction()))
break;
...
while (0);
return error_code;
顺便说一句,这遵循更常见的模式:0
可以,其他一切都不是。根据需要调整)
你甚至可以使用宏来混淆它:
#define RUN_AND_BREAK_ON_ERROR(rc, f, ...) \
if (0 != (rc = f(__VA_ARGS__))) \
\
break; \
int foo(void)
int error_code;
do
RUN_AND_BREAK_ON_ERROR(error_code, FirstFunction, <args go here>);
RUN_AND_BREAK_ON_ERROR(error_code, SecondFunction, <args go here>);
...
while (0);
return error_code;
【讨论】:
@AnttiHaapala:为什么?为什么这种事经常发生在我身上……: 可能是 1,3,7-三甲基黄嘌呤缺乏症 ;) 或者 Visual Basic 太多【参考方案4】:if( (error_code = FirstFunction()) || (error_code = SecondFunction()) || ... )
return error_code ;
return error_code; //denoting no error.
这将只返回第一个返回非零的函数。这个想法是,对于if
语句,返回nonzero
的第一个函数将短路整个评估并从返回非零error_code
的函数返回error_code
。另一件事是赋值语句的值是分配的值。这就是它起作用的原因。
更简单的方法是顺序 if-else
if( error_code = FirstFunction() )
else if( error_code = SecondFunction() )
...
return error_code;
【讨论】:
这很接近,我喜欢它在比较中捕获错误代码的方式,但 Benoit 的答案更接近我想要的。 注意:2else
不是必需的。
@chux.: 你是说最后一个?早些时候我打错了电话FirstFunction
两次。你是这个意思吗?
不需要else
s,因为当if
条件失败时,return
被执行;但是在第二个示例中,OP 问题的重点不是避免多个返回点吗?
@DavidBowling.:已编辑。实际上我已经提供了
- 一个空白的if
也可以。【参考方案5】:
如果所有这些函数都采用相同类型的参数并具有相同的返回类型,则可以将它们放在一个函数数组中并对其进行迭代。当发现错误时,它会简单地跳出循环并返回。
int (*function_array[max_array])();
/*Fill the array with the functions you need*/
for(i=0;i<max_array;i++)
if((error_code=function_array[i]())!=OK)
break;
return error_code;
(OK
是这些函数的成功返回值)
【讨论】:
我知道 OP 没有提到参数,但是,这种使用函数指针数组的方法仍然依赖于使用相同参数的所有函数,数量和类型相同。 确实我没想到。也许它可以用另一个参数数组来解决。但在这一点上,它可能不值得。【参考方案6】:嗯,有一个用过的,例如在 Linux 内核中:
int somefunc(whatever)
if (do_something())
ret = -EINVAL;
goto err;
if (do_something_else())
ret = -EPERM;
goto err;
/* ... */
ret = 0;
err:
some_mandatory_cleanup();
return ret;
但我怀疑这会更不受欢迎。 (在你尖叫之前,重点是最后的强制清理。goto
将其安排为始终执行,但仍将其排除在外。)
真的,我认为您的第一个 sn-p 中的代码很好,问题在于您的指南。即使我们只在一处写return error_code;
,也不足以保证保存在变量中的错误代码总是正确的,或者函数完成了所有可能需要的清理工作。 (考虑分配内存的东西,无论如何都必须释放它。)
【讨论】:
尽管我很想更改指南,但它们是我们客户整体项目要求的一部分,不在我的控制范围内。 是的,如果我尝试使用 goto,他们会解雇我:D以上是关于第一次检测到错误后返回错误代码的主要内容,如果未能解决你的问题,请参考以下文章
远程桌面提示:由于在客户端检测到一个协议错误(代码0x1104)……