如何在c ++中设计错误代码?

时间:2017-09-26 06:30:08

标签: c++ function error-handling

我正在写一个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返回错误时,我该怎么办?我想出了一些方法:

  1. 设计我的错误代码。错误代码的数量是func1和func2的总和。当调用堆栈很深时,错误代码的数量会变大。

  2. 只需返回func1或func2的结果。由于错误代码可能重叠,因此无法知道哪个功能失败。

  3. 设计我的错误代码,代码数量等于函数数量。调用者只知道哪个函数返回错误,但他不知道其他原因。

  4. 抛出包装失败的函数名称及其错误代码的异常。

  5. 最佳做法是什么?

    上一个代码示例含糊不清。我修改了它。

2 个答案:

答案 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,错误代码背后的逻辑如下:

  1. 如果例程(func0)在某个子例程(func1)中发生错误时失败,则例程应立即停止并报告给调用者。

    否则没有意义。例如,如果要func0来制作咖啡,func1是要获得一些咖啡豆而func2是要酿造,那么没有咖啡豆,你只是在酿造空气。告诉别人你可以酿造空气并不是很有帮助。

  2. 如果例程可以优雅地处理其子例程中的错误,那么对于例程的调用者来说它根本不是错误。在这种情况下,不应返回任何错误。

  3. 因此,第一个案例的程序结构应该只是

    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;
    }