Patrick
Patrick

Reputation: 141

How do I design error codes in c++?

I am writing a c-style function:

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 and func2 are c functions and they have their own error codes. What should I do when func1 or func2 return an error? I figure out some ways:

  1. Design my error codes. The number of error codes is the sum of func1's and func2's. When the call stack is deep, the number of error codes becomes large.

  2. Simply return the result of func1 or func2. There is no way to know which function fails since their error codes may overlap.

  3. Design my error codes and the number of the codes is equal to the number of functions. The caller just know which function return error, but he don't know the further reason.

  4. Throw an exception wrapping the failed function name and its error code.

What's the best practice?


The previous code example is ambiguous. I modified it.

Upvotes: 0

Views: 753

Answers (2)

Passer By
Passer By

Reputation: 21130

Echoing tobi303's comment, the logic behind error codes is as follows:

  1. If a routine (func0) will fail when an error occurs in a certain subroutine (func1), the routine should stop immediately on error and report back to the caller.

    To do otherwise makes no sense. For example, if func0 is to make coffee, func1 is to get some beans and func2 is to brew, then without the beans, you are just brewing air. Telling someone you can't brew air isn't awfully helpful.

  2. If a routine can gracefully handle an error in its subroutine, then its not an error at all for the caller of the routine. In this case, no error should be returned.

So the structure of your program for the first case should be simply

int func0()
{
    if(int err = func1())
        return err;
    if(int err = func2())
        return err;
    return 0;
}

And the second case

int func0()
{
    if(int err = func1())
        handle(err);
    if(int err = func2())
        return err;
    return 0;
}

Upvotes: 0

gsamaras
gsamaras

Reputation: 73366

Why expose the complexity of func0() to the caller? Usually the caller is not interested in what happens in the body of the function, he just wants the job to be done.

func0() should notify the user on why it failed to complete its goal (to terminate without errors). They are many ways to do that. One example could be this:

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

Note that here we don't allow func2() to be executed if func1() fails, since that might be dangerous.

For instance, if func1() is suppose to allocate space for an array that func2() is going to use, then let's say that func1() fails (because malloc() failed). func2() should not be called, since func1() failed in that case, because the array that func2() expects to be ready for use, is not available at runtime.

Upvotes: 2

Related Questions