Posted on 13 May 2014
printf for debugging is simple enough for small projects, but what if
we want more information?
We start off by defining a simple
LOG macro to essentially alias
with a simple way to toggle messages:
Adding Debugging Levels
Okay, so how about separate debugging levels? Traditionally, loggers print
messages from the lowest defined level on up. Here we’ll use
ERROR, but you can add your own. This system can be implemented by simply
adding a few lines:
Using preprocessor constants and conditionals, we can construct a more robust tiered logging system.
There are several interesting additions in this iteration. First, we see that
the strings “[WARN ]” and “[ERROR]” are prepended directly to msg; there is no
+ or other operators to signify the concatenation.
On the same line is
## args. Consider the case where we run
LOG("Hello World") with
LOG from the first iteration. Because the varargs
are empty, we would essentially be writing
printf("Hello World", ), causing a
syntax error. Thus, this extension works around that issue and makes varargs
optional. Note that this is a GCC extension and may not be supported by all
compilers. You can read more on this in the official GCC documentation1.
Printing Source Code Metadata
One of the most frustrating aspects of debugging is not knowing where messages
are coming from. Of course, there’s always wading through
grep or one of its
self-proclaimed successors (Ack or
Ag), but there has to be an easier way.
The C preprocessor conveniently provides the
__func__ macros to help with this dilemma. These macros can be put to quick
use by factoring logging logic into a separate
(Props to StackOverflow for help on preprocessor variables2).
At this point, our library provides logging levels and extra source code metadata to help with debugging.
Simple, effective logging is crucial, especially when building complex systems and triaging bugs. You can grab the final code in Gist form here.
Questions or suggestions? Start a discussion in the comments below!