tags:

views:

108

answers:

3

Hi, by design, in the environment I'm working right now I can't use a debugger to try to detect bugs, so pretty much always when I need to debug a functionality I end up outputting some info.

To do that I've done the following:

#ifdef DEBUG
    #define printd(x) printf x
#else
    #define printd(x)
#endif

So when I need to print some debug info I use printd() instead of printf().

The problem I've found is that I need a leveled system, there are messages that may be important in a determined debug level, but irrelevant when debugging other parts of the code.

So my question is, how can I implement a leveled debug system? I value simplicity, I mean, I prefer my actual system than needing a lot of code or confusing code when using it. Something like printd(level, format, ...) would be awesome.

+4  A: 

Sure, there are more elegant ways to do this, of course, but this works just fine

#ifdef DEBUG
 extern int g_debuglevel;
 #define printd(level, x) (level <= g_debuglevel) ? 0 : printf x
#else
 #define printd(level, x)
#endif

Although personally I prefer this

#ifdef DEBUG
 extern void printdf(level, fmt, ...);
 #define printd printfd
#else
 #define printd
#endif

where printdf is a function that tests the level and then calls vprintf passing along the fmt and va_args.

John Knoeller
There are sound maintenance reasons for ensuring that the code is always expanded so that the compiler always compiles the debug code. Use `if (0) { ...debug printing...}` or equivalents. It greatly reduces the chance of the debugging being broken when you next activate it - which might be years after the last time.
Jonathan Leffler
@Johnathon: Actually, I simplified a bit to match the code he posted. my actual debug macro expands to some code whether debug is defined or not. one lesson at a time.
John Knoeller
@Johnathon: Also, building debug and retail on every checking solves the maintenance issue without the cost of bloating the retail code with debug information.
John Knoeller
There is no code bloat in the 'retail' code unless the compiler is broken; it will optimize away the code after 'if (0)'. I can agree with one lesson at a time - though it doesn't hurt to point out that the current lesson is not the final word on the subject.
Jonathan Leffler
@Johnathon Leffler: that has not been my experience, the optimizer can _usually_ discard the debug code, but it sometimes has trouble when it references variables outside of the debug block.
John Knoeller
+1  A: 

See the answers to:

These will give you a lot of pointers on what to do.

Jonathan Leffler
Yes, you can do fancy new things with a C99 compliant compiler, but most of us don't have that yet.
John Knoeller
@John Knoeller: As I point out in my answer to the first of the two questions listed, there is a perfectly viable solution for C89 which I used until a couple of years ago. It isn't as neat and tidy as the C99 solution using the `__VA_ARGS__` macro arguments, but it most certainly works.
Jonathan Leffler
Thank you! I've done something similar in the end, and now I now it's better to allow the compiler see debug code in release builds.
Carla Álvarez
+1  A: 

If you want to go the extra step and log your level debug statements they you could try log4c. http://log4c.sourceforge.net/

in the printfd function described above, you can also check for an environment variable say DEBUG_LOG_LEVEL to dynamically switch on and off your logging.

I used a similar technique to implement a lightweight leveled logging library for an embedded linux environment.

Also for an example of log4c - http://log4c.sourcearchive.com/documentation/1.2.1/helloworld_8c-source.html Thanks to google search :)

ka05
Thanks! But at least for now (it's kind of a small project) the simple logging suggested is enough for me.
Carla Álvarez