0

Error checking in C is a task that is very verbose and makes the code unreadable. In C++ you have exceptions, but when I use C++ to call C functions, the headaches come back. I wish there was a "syscalls wrapper for C++" where all the functions have the same names and parameters, but where errors are turned into exceptions and that's all. That would be game changing.

Trying to solve that verbosity problem when interacting with C functions/syscalls from C++, I came up with the following solution (simplified here):

void ko(char const* doingwhat) // or ko_check or whatever
{
   if (errno != 0)
      throw std::runtime_error(doingwhat);
}

void some_method()
{
    errno = 0;
    int fd = open(blablabla, blablabla); ko("opening the file");
    void* ptr = mmap(blablabla, blablabla); ko("mmaping it");
    
    struct stat st; fstat(fd, &st); ko("getting stats");
    // etc etc etc
}

The method is to directly ignore return values and check errno instead. Since errno is thread local and can only change if there's an error in a libc call, with setting errno = 0 at the beginning of your method would be enough.

In C doing that would be pointless (or at least not that benefitial) because you cannot get rid of returning in case of error anyway, and that's why I think I have never seen that kind of approach mentioned in any discussions about error handling.

Is there any important pitfall in that approach of mine? Can errno be != 0 in surprising situations? Anything to be aware of? That fact that I have never seen this "approach" discussed anywhere makes me wonder if there's any good reason for it, because I don't see any.

NOTE: Of course, you have to be careful about functions that set errno in conditions that might be ok for you. Know the functions you use very well and don't let the habit of just calling ko cause you forget about checking the man pages of the functions you use, continuously.

7
  • 1
    An error isn't the same thing as a response you don't expect. It might be a valid response but not an error. It's bad to ignore the function return value, which may be what you called the function to get. Commented May 26, 2024 at 19:40
  • Those are not system calls ("syscalls") but plain C function calls. Your solution, to cram another function call in the same line is horrible, rather create a function template that wraps the function you call. Or, even better, find an existing library that does that! After all, your requirements are not particularly unique. Commented May 26, 2024 at 19:43
  • 6
    Generally, both the C and the POSIX specification says that the value of errno is undefined unless the called function returned with a failure indicator. There are a few exceptions, but the functions you use are not in that (very) short list. Commented May 26, 2024 at 19:47
  • 3
    It's not impossible for a function to call another function that returns an error, and not return an error itself, but still leave errno set to a non-zero value because of that. Commented May 26, 2024 at 20:04
  • 9
    The value becomes undefined after each call you make. You must always check if the function actually failed before you check errno. Commented May 26, 2024 at 20:06

1 Answer 1

4

You can not replace error checking with exceptions when wrapping C with C++. Per the (draft) C11 standard 7.5 Errors <errno.h>, paragraph 3:

The value of errno in the initial thread is zero at program startup (the initial value of errno in other threads is an indeterminate value), but is never set to zero by any library function. The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

Note these two statements:

[errno] ... is never set to zero by any library function.

and.

The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

So you can never rely on the value of errno unless you have already established you've received an error from a function that's documented to set errno.

So you'd have to wrap all your C calls with C++ calls in ways that handle errors properly in order to turn them into exceptions.

Nevermind relying on exceptions to handles expected conditions is widely considered a VERY bad practice. All files end - tossing an exception on EOF is a misuse of exceptions - it's in no way exceptional.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm not relying on exceptions to handle expected conditions, because in my context and the functions I'm using these are not expected conditions; these are errors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.