Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant error checking

Our code (in a simple library implementation) is beginning to look like this:

err = callToUnderlyingLibrary1();
if (err!=0) {
printf ("blah %d\n", err);
...
}

err = callToUnderlyingLibrary2();
if (err!=0) {
printf ("blah %d\n", err);
...
}

err = callToUnderlyingLibrary3();
if (err!=0) {
printf ("blah %d\n", err);
...
}

This is cumbersome and ugly. Is there a better way to do this ? Perhaps using the C preprocessor ? I was thinking something like:

CHECK callToUnderlyingLibrary1();
CHECK callToUnderlyingLibrary2();
CHECK callToUnderlyingLibrary3();

where the CHECK macro invokes the function and does the rudimentary error checking.

Are there preferred idiomatic ways of handling this ?

like image 501
Ren Avatar asked Aug 03 '11 19:08

Ren


People also ask

How do you check errors in Golang?

Errors can be returned as nil , and in fact, it's the default, or “zero”, value of on error in Go. This is important since checking if err != nil is the idiomatic way to determine if an error was encountered (replacing the try / catch statements you may be familiar with in other programming languages).

How do you use try catch in Golang?

This method is also known as try-catch-finally In this method, in the try block the error-free code has been executed and if it has found some issue it will be handled in the catch block and finally block will be executed all the things at any cost.


2 Answers

Another macro-based approach which you can use to mitigate the shortcomings in C fairly easily:

#define CHECK(x) do { \   int retval = (x); \   if (retval != 0) { \     fprintf(stderr, "Runtime error: %s returned %d at %s:%d", #x, retval, __FILE__, __LINE__); \     return /* or throw or whatever */; \   } \ } while (0) 

Then to invoke it you have:

CHECK(doSomething1()); CHECK(doSomething2()); // etc. 

For bonus points you could easily extend the CHECK macro to take a second argument y that is what to do on failure:

#define CHECK(x, y) do { \   int retval = (x); \   if (retval != 0) { \     fprintf(stderr, "Runtime error: %s returned %d at %s:%d", #x, retval, __FILE__, __LINE__); \     y; \   } \ } while (0)  // We're returning a different error code CHECK(someFunction1(foo), return someErrorCode); // We're actually calling it from C++ and can throw an exception CHECK(someFunction2(foo), throw SomeException("someFunction2 failed")): 
like image 52
fluffy Avatar answered Sep 20 '22 00:09

fluffy


Usually, in C, one uses goto for error handling:

int foo()
{
    if (Function1() == ERROR_CODE) goto error;
    ...
    struct bar *x = acquire_structure;
    ...
    if (Function2() == ERROR_CODE) goto error0;
    ...

    release_structure(x);
    return 0;

error0:
    release_structure(x);

error:
    return -1;
}

This can be improved with macros and more clever instruction flow (to avoid repeating cleanup code), but I hope you see the point.

like image 20
Alexandre C. Avatar answered Sep 18 '22 00:09

Alexandre C.