There are errors, and there are errors.
Programming-errors are either handled by assertions, which only fire in debug-mode, saving release-mode from the associated costs, or by immediate abort with an error-message. Trying to recover risks more damage to the users data and is thus generally inacceptable.
The possibility of outside interference (radiation, wear and tear on the computing system) argues for more checking of the internal consistency left in the release version, and using a supervisor process to restart if needed.
Somewhat expected outside errors, like insufficient resources, needed resources denied (cannot gain sufficient access), input errors, and errors from peers, servers, and clients on the other hand generally have to be handled gracefully. The main ways for doing that are:
Handle it yourself. For example retry, wait, or try alternative. Often cannot be done, and certainly degrades the control the caller has.
Notify the caller. Let him handle that in any appropriate way.
- If the return-value has some invalid states (often null-pointer, negative integers, and the like) use one of those, and optionally store additional error-info elsewhere (see
errno
).
- Return an error-code, data has to be returned through out or in-out parameters. Might be a bit more cumbersome, but can be applied uniformly.
- Return a structure combining error-code and return-data. Especially popular in functional languages, and gained more popularity with Rust and other languages eschewing exceptions.
- Use exceptions. Not directly applicable to C, though take a look at
setjmp
and longjmp. It has been done before, for example in the implementation of the Lua interpreter.
- Use a callback if an error is encountered. This is also often used for periodic status-information in a long-running possibly non-asynchronous operation to allow feedback to the user. The infamous Annex K goes that route. And one of the important criticisms is the use of the callback, especially that it isn't even thread-local, not being passed every call is somewhat easier to digest.