Very often, I have to use multiple libraries that handle errors differently or define their own enums for errors. This makes it difficult to write functions that might have to deal with errors from different sources, and then return its own error code. For example:
int do_foo_and_bar()
{
int err;
if ((err = libfoo_do_something()) < 0) {
// return err and indication that it was caused by foo
}
if ((err = libbar_do_something()) < 0) {
// return err and indication that it was caused by bar
}
// ...
return 0;
}
I've thought of two possible solutions:
int translate_foo_error(int err)
, and I would write my own string representations for each error.struct my_error
that holds both an enum identifying the library and the error code. The translation to string would be delegated to an appropriate function for each library.This seems like a problem that would come up very often, so I'm curious, how is this usually handled? It seems like the former is what most libraries do, but the latter is less work and plays on the tools already provided. It doesn't help that most tutorials just print a message to stderr and exit on any error. I'd rather have each function indicate what went wrong, and the caller can decide from that how to handle it.
The C programming language does not support exception handling nor error handling. It is an additional feature offered by C. In spite of the absence of this feature, there are certain ways to implement error handling in C. Generally, in case of an error, most of the functions either return a null value or -1.
C language uses the following functions to represent error messages associated with errno: perror() : returns the string passed to it along with the textual represention of the current errno value. strerror() is defined in string. h library.
The answer is, it depends on your code's constraints.
collectd prints to standard error then bails if it hits a fatal error.
OpenGL will set some shared state that you can query. Ignoring this error often results in undefined behavior.
Collectd has lots of threading concerns, and most errors can't be fixed or recovered from by the program. For example, if a plugin depends on some library, and a call to that library fails, the plugin knows the most about how to recover from that error. Bubbling that error up isn't helpful as collectd core will never know about plugin N+1
On the other hand, OpenGL applications are usually responsible for any errors encountered and can attempt to correct errors. Such as, if they are attempting to compile a shader, but might have a special one for a specific vendor or platform.
Based on your program's design, consider the following:
GetLastError()
function? Update:
Going with the global state option you might have something like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
char* last_err = NULL;
void set_err(char* error_message) {
if(last_err)
free(last_err);
/* Make a deep copy to be safe.
* The error string might be dynamically allocated by an external library.
* We can't know for sure where it came from.
*/
last_err = strdup(error_message);
}
int can_sqrt(int a) {
if(a < 0) {
set_err("We can't take the square root of a negative number");
return 0;
}
return 1;
}
int main(int argc, char* argv[]) {
int i = 1;
for(i = 1; i < argc; i++) {
int square = atoi(argv[i]);
if(can_sqrt(square)) {
fprintf(stdout, "the square root of %d is: %.0f\n", square, sqrt(square));
} else {
fprintf(stderr, "%s\n", last_err);
}
}
return 0;
}
Running the above program
$ ./a.out -1 2 -4 0 -6 4
We can't take the square root of a negative number
the square root of 2 is: 1
We can't take the square root of a negative number
the square root of 0 is: 0
We can't take the square root of a negative number
the square root of 4 is: 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With