1

Error handling in C code

#define CHECK_FOR_ERRORS(ret)                           \
    if(ret != CY_U3P_SUCCESS)                           \
    {                                                   \
        handleCriticalError(ret, __FILE__, __LINE__);   \
    }

Intended usage:

CHECK_FOR_ERRORS(CyU3PPibInit(CyTrue, &pibClock));

No return variables, no extra code lines, only wrapping important function calls with this macro.

But it doesn't work. The macro does not evaluate the function call, it only casts the function pointer to int.

How do I make this work?

Community
  • 1
  • 1
Vorac
  • 8,726
  • 11
  • 58
  • 101
  • Macros operate at compile time, therefore they never evaluate function calls. You should see macros as fancy text substitution devices that are expanded by the preprocessor. – hetepeperfan Dec 13 '13 at 16:04
  • @hetepeperfan, can I do this with a function? With anything? – Vorac Dec 13 '13 at 16:05

2 Answers2

2

You macro calls the function twice, first the actual call, and a call for error handling. Try this:

#define CHECK_FOR_ERRORS(ret)                           \
    do { int r = ret; if (r != CY_U3P_SUCCESS) {\
    handleCriticalError(r, __FILE__, __LINE__);   \
    } while(0)

You can see how the macro is interpreted with the -E flag of gcc, or a similar flag for your compiler. And in general, try to use each macro argument only once in the macro definition to prevent this kind of problems.

perreal
  • 94,503
  • 21
  • 155
  • 181
  • 1
    I think it worked beautifully! I am replacing a more verbose error reporting scheme, and the code dropped to half in size! – Vorac Dec 13 '13 at 16:27
0

Personally I would do this much easier. Assuming CyU3PPibInit(CyTrue, &pibClock) initializes some library and returns 0 if successful. I would do something like the following:

if ( CyU3PPibInit(CyTrue, &pibClock) != 0){
    fprintf(stderr, "At %s : %d: unable to load CyU3PPibInit, ", __FILE__, __LINE__);
    /*eiter abort here or sets some variable that your subsequent program flow doesn't use  this library */
}
/*continue without the library*/

this way you have simple to understand code. Marco substitution makes code usually difficult to read.

hetepeperfan
  • 4,292
  • 1
  • 29
  • 47