synaptik
synaptik

Reputation: 9509

How to embed debugging statements in C++ using macros

I'm writing a program, and I would like to output different types of debugging information depending on the value of various macro variables (so that I can change the value of a flag that then causes different levels of information to be written to the screen).

For example, suppose I have the following code that prints information to the screen about my program (call this D1):

cout << "% Percentage complete: "
     << ceil((static_cast<double>(idx)/static_cast<double>(ITERATIONS))*(100.00))
     << "%" << endl;
cout << "x = [ x; ";
for(int i=0; i<space.getDimension(); i++)
    cout << visited.vec[visited.bestIndex].x[i] << "\t";
cout << "];" << endl;

Now, also suppose I have the following code that prints different information to the screen about my program (call this D2):

cout << "best = [ best; "
     << visited.vec[visited.bestIndex].meanQALY() << "];\n" << endl;
space.displayConstraintsMATLAB(idx+1);

I would like to be able to insert statements such as #D1 and #D2 at certain places in my code and have the macro processor replace these statements with the above code blocks.

How can I do this?

(I'm happy to hear suggestions for different ways of doing this, if macros are not an ideal solution.)

Upvotes: 0

Views: 1463

Answers (2)

djf
djf

Reputation: 6757

Seems to me what you're looking for is a logging facility. Check out this thread for some suggestions.

Why using a whole framework instead of Macros?

The problem is that proper logging is more difficult than it seems. There are threading issues, sessions, classes and object instances are factors you have to consider. Also log file buffering, roll over and compressing log files are issues you have to think about. You might also want to log over the network or to syslog (or both), or into a database. Correctly implementing all of this yourself is a lot of work.

Are Macros any good?

Sure! In our project we have defined a single macro called LOG which wraps calls to our logging framework (we're using log4cpp). If one day we device to move to another framework, we only have to redefine our LOG macro in a single place instead of combing the entire codebase. This works because most logging frameworks share a similar interface usually consisting of the log-level and the message string.

Upvotes: 1

Pyrce
Pyrce

Reputation: 8571

You can either make a macro which does debugging for you -- like:

#ifdef D1
#    define DEBUG(var) //Debug 1 print implementation here
#elif defined D2
#    define DEBUG(var) //Debug 2 print implementation here
#else
#    define DEBUG(var) //No-op
#endif

Otherwise you could make a debug function, then inside of that function do a similar check with #if def statements to see how you want to process the input. The function version has a little more early type detection so it tends to tell you about errors in a nicer fashion when you try printing something that's not processable (some custom object). Additionally if the function is a no-op (has no internals in Release mode) then the function call will be discarded by your compiler when any optimization flags are present, so you won't pay any additional cost in Release mode as a result of Debug calls.

For my own debug calls I usually defined a stream operator, much like std::cout, to convert all the inputs to strings or char* and then punt them to a a debug function if DEBUG is defined or print nothing. For exceptions and logging you can do a similar metric with varying levels of severity (Info, Warning, Error, etc). This tends to make it as easy to throw debug code around in C++ as it is in more modern languages imo.

Upvotes: 1

Related Questions