我正在写一个c风格的函数:
enum {
EFUNC1,
EFUNC2,
}
int func0() {
int err = 0;
if((err=func1())!=0) {
// return err or return EFUNC1
}
if((err=func2())!=0) {
// return err or return EFUNC2
}
return 0;
}
func1和func2是c函数,它们有自己的错误代码。当func1或func2返回错误时,我该怎么办?我想出了一些方法:
设计我的错误代码。错误代码的数量是func1和func2的总和。当调用堆栈很深时,错误代码的数量会变大。
只需返回func1或func2的结果。由于错误代码可能重叠,因此无法知道哪个功能失败。
设计我的错误代码,代码数量等于函数数量。调用者只知道哪个函数返回错误,但他不知道其他原因。
抛出包装失败的函数名称及其错误代码的异常。
最佳做法是什么?
上一个代码示例含糊不清。我修改了它。
答案 0 :(得分:2)
为什么要将func0()
的复杂性暴露给调用者?通常调用者对函数体内发生的事情不感兴趣,他只是希望完成这项工作。
func0()
应该告知用户它未能完成目标的原因(终止没有错误)。他们有很多方法可以做到这一点。一个例子可能是这样的:
// On success: Return 0
// On error: Return -1
int func0() {
if(func1() == -1) {
printf("Error in func0: func1 returned error code -1");
return -1;
}
if(func2() == -2) {
printf("Error in func0: func1 returned error code -2");
return -1;
}
return 0;
}
请注意,如果func2()
失败,我们不允许执行func1()
,因为这可能很危险。
例如,假设func1()
为func2()
将要使用的数组分配空间,那么假设func1()
失败(因为malloc()
失败) 。 func2()
应该不被调用,因为func1()
在这种情况下失败,因为func2()
期望可以使用的数组在运行时不可用。
答案 1 :(得分:0)
回应tobi303's comment,错误代码背后的逻辑如下:
如果例程(func0
)在某个子例程(func1
)中发生错误时失败,则例程应立即停止并报告给调用者。
否则没有意义。例如,如果要func0
来制作咖啡,func1
是要获得一些咖啡豆而func2
是要酿造,那么没有咖啡豆,你只是在酿造空气。告诉别人你可以酿造空气并不是很有帮助。
如果例程可以优雅地处理其子例程中的错误,那么对于例程的调用者来说它根本不是错误。在这种情况下,不应返回任何错误。
因此,第一个案例的程序结构应该只是
int func0()
{
if(int err = func1())
return err;
if(int err = func2())
return err;
return 0;
}
第二种情况
int func0()
{
if(int err = func1())
handle(err);
if(int err = func2())
return err;
return 0;
}