Showing posts with label c. Show all posts
Showing posts with label c. Show all posts

2011-11-10

Debug utility function caveats

What's wrong with the following code assuming there is no danger of null dereference?

int debug;
module_param(debug, int, 0644);

...

void dump_xyz_info(struct xyz *obj)
{
    if (!(debug & DEBUG_INFO))
        return;

    dev_info(mydev, "[a=%d b=%d c=%d]\n", obj->a, obj->b, obj->c);
}
While I though it was a good idea to incorporate the debug flag check in my debug utility method, I learned later that it prevents me from using this method for debugging, and having to resort to ugly tricks like this:

void dump_all_info(struct the_obj *obj)
{
    int old_debug = debug;
    debug = DEBUG_INFO;
    dump_xyz_info(obj->xyz);
    dump_pqr_info(obj->pqr);
    debug = old_debug;
}
OK, so I did not actually do this and fixed the issue at the first place. But how many times have we seen ugly tricks in the code like the above? Now I cherish expressions like:

if (debug & DEBUG_INFO)
    dump_xyz_info(obj->xyz);
Cheers!

2010-03-22

#1 C Macro Pet Peeve: use do while 0

I cannot fathom why I still see compound macros like:
#define TRACE(fmt, ...) { \
printf(fmt, ##__VA_ARGS__); fflush(stdout); \
}

Please, use do while 0:
#define TRACE(fmt, ...) do { \
printf(fmt, ##__VA_ARGS__); fflush(stdout); \
} while (0)

Don't worry. Your (any remotely recent) compiler will not generate any assembly code for the "do while 0". For an explanation, just search do while 0. The basic idea is that you want these kind of macros to behave like normal C void methods. However, if you use the original macro in an expression such as "if (expr) TRACE("yes"); else TRACE("no");", the semicolons after the expansion will cause syntax errors.

For more options to use instead of do while 0, see G_STMT_START/END macros in glib.h, depending on what your compiler allows:
#define TRACE(fmt, ...) if(0) { \
printf(fmt, ##__VA_ARGS__); fflush(stdout); \
} else (void)0

#define TRACE(fmt, ...) (void) ({ \
printf(fmt, ##__VA_ARGS__); fflush(stdout); \
})

C Macro School

C is language I use most commonly. One of the least developed features of C (and coincidentally my favorite feature) is its macro preprocessor. Luckily, during the past decade GCC has implemented many improvements that ease the creation of very powerful macros.

Over the course of my projects, I very often work with someone else or on someone else's code, and I am surprised that even after 15 years, I keep seeing the same mistakes. So I am going to list my list of "My 10 Greatest Pet Peeves with C Macros". Well there may not be 10, but there are many. So let's begin...