Enable debug print statements if compiled with debug flag - c++

Let's say I have a project with many functions. For debugging purpopses, I want each one of them print out a diagnostic message (or a few) when called:
int f(int arg) {
cerr << "f() called with argument" << arg << endl;
int ret = 42;
cerr << "f() returned " << ret << endl;
return ret;
}
and so on. In one function, there may be as many as five to six messages printed out on cerr. I want to be able to disable them unless a debug flag (like NDEBUG) is set. One thing I could do is wrap each cerr statement with an if-statement.
#ifdef NDEBUG
const bool DEBUG_ON = true;
#else
const bool DEBUG_ON = false;
#endif
int f(int arg) {
if (DEBUG_ON) {
cerr << "f() called with argument" << arg << endl;
}
int ret = 42;
if (DEBUG_ON) {
cerr << "f() returned " << ret << endl;
}
return ret;
}
But it can get really tedious and, in the end, virtually unreadable with a couple dozens of such statements. My idea was to replace cerr with a custom object with an overloaded << operator which would send any arguments passed to it "into the void" like this:
class NullOutStream {
public:
NullOutStream operator<<(...) {
return *this;
}
};
NullOutStream debug_out;
#ifdef NDEBUG
#define debug_out cerr
#else
#define debug_out debug_out
#endif
Although it works perfectly, it doesn't seem very elegant. Is there a standard/nicer way to accomplish this?

There is no "standard" way to do this. There are many logging/assertion libraries that deal with similar issues, and there are different approaches to solve this. A few things to keep in mind:
It may or may not be desirable to keep the side effects of your log statement (as yours does). For example, if you did something like this:
debug_out << ++i;
This would increment i no matter whether you are in debug mode or not. This is probably desirable in this case. Conversely, if you do this:
debug_out << some_object.expensive_to_string_operation();
This would call expensive_to_string_operation() even when you are not in debug mode. This is probably not desirable in this case.
This would not happen if you used printf-style debug macro, e.g. something like this:
#ifdef NDEBUG
#define logf(...)
#else
#define logf(...) printf(__VA_ARGS__)
#endif
The reason being that when in non-debug mode, the arguments would be removed by the preprocessor.
You may want to do other things before or after each log statement, e.g. record a time stamp, flush a log file etc. It is possible to do this with streams by using destructor tricks, but it is more complicated to implement. It is much easier to do this using a function call, e.g. something like this:
#define log(msg) printf("%s: %s\n", timestamp(), msg)
You may want to record file name / line number with your logs. Again, this is easier to do with a function call than with a stream.
Streams may be better if you want custom formatting by object type - the printf interface doesn't lend itself to that very well.
I would recommend to have a look at some existing logging libraries to get an idea of different approaches. I suggest looking at Google's glog library because it has an interesting combination of using streams while retaining the ability to do 'per call' things (e.g. record time stamps, line numbers etc).

Related

Define then Undefine Preprocessor Variables within Macro

I would like to create a macro like the following, which would be used to create two functions: one with debugging enabled and one without debugging enabled.
#define MakeDebuggerFunction(funName, funContents)\
void funName() funContents\
#define DEBUGGING\
void funName ## _debugging() funContents\
#undef DEBUGGING
And the way this would be used would be like the following
MakeDebuggerFunction(DoWork,
{
std::cout << "Doing Work" << std::endl;
#ifdef DEBUGGING
std::cout << "Printing Verbose" << std::endl;
#endif
}
)
This would result in two functions: DoWork and DoWork_debugging. Where both functions would have the same exact "guts" of the code for that function, but the debugging function would also have some verbose printing added.
The reason I want both functions created is because my GUI application has a "developer mode" which I can use when I'm out of the office and onsite with customers, where I don't have the luxury of a true debugging environment.
Many of these functions are also very processing intensity so I want to avoid doing something like adding a permanent if(DeveloperMode) {} statement wrapping my verbose code.
Any help/suggestions I can get would be greatly appreciated.
I think this is what #Justin was suggesting
I would make my wrapper function like this:
void DoWork_Wrapper()
{
if (DeveloperMode)
DoWork(..., true);
else
DoWork(...., false);
}
and the worker function would be:
void DoWork(..., bool DeveloperMode)
{
/// do some stuff
if (DeveloperMode)
/// print verbose
}
So when I make the call to DoWork(..., false) the compiler has already optimized out the if-statements?
How about doing it this way. You can make your debug function inline and it will be completely transparent. Of course you will have to work around more complex debug messages and adjust your debug function appropriately. It would be much better than making duplicates of your functions.
void debug(string s) {
if (DeveloperMode) {
std::cout << s << "\n";
}
}
std::cout << "Doing Work" << std::endl;
debug("Printing Verbose");
Or you can use one of the looging libraries out there. E.g. Log4c.
I'm not sure if this is exactly what you want but if you can compile one version with debugging enabled and one without you can just add a DEBUGGING compile flag to the debugging one and do the following
#ifdef DEBUGGING
#define debugPrint(verboseMessage) \
std::cout << verboseMessage << std::endl;
#else
#define debugPrint(verboseMessage)
#endif
This will make it so you can always call this macro and if debugging is on it will actually print your message, otherwise nothing will happen.
HTH!

Concatenating a string and passing as a parameter?

I wrote my own logger that I can use as follows:
LOG("This is the number five: " << 5 << ".");
I'd like to write an error checking method that simply takes a return code, checks if it's an error, and if so prints an error message
Thus, I'd like to turn:
if(result == -1)
{
LOG("ERROR! We got a result of: " << result << ".");
// Do some other stuff
}
into:
checkForError(result, "ERROR! We got a result of: " << result << ".");
void checkForError(int result, SomeStringType message)
{
if(result == -1)
{
LOG(message);
// Do some other stuff
}
}
is this possible? I've tried passing it as a char*, a std:string, and as a stringstream, but I can't seem to get it to work correctly
Is there any way to do this so I'm simply concatenating the error message in the call to the function?
Yes, it's possible. You could do it like this:
#define LOG(X) \
do { \
std::ostringstream log_stream; \
log_stream << X; \
LOG::log_internal(log_stream.str()); \
} while (0)
where LOG::log_internal might be declared in your logger header like
struct LOG {
static void log_internal(const std::string &);
};
The main drawback of this is that it's not the most hygienic macro ever -- if the argument X contains semicolons, then you could have additional statements executed inside the macro's scope, and there won't be a compiler error. This macro is far from cryptic though in my opinion, and fortunately you don't actually have to worry about an attacker performing SQL-injection-esque attacks against your macros.
I use loggers that basically look like this in my projects, and I learned to do it this way from other projects. (Actually the one I use is a little more developed, it also passes __FILE__ and __LINE__ to the LOG::log_internal function, and there's log channels and log levels which may or may not be active etc. etc...)

streamed variables as a function parameter in C++

When you stream variables to an output stream such as cout, type conversion is automatic. What I'm trying to figure out is how to do this via a function call, for example:
inline void DEBUG(ostream& s) // Don't know if this prototype is appropriate
{
cout << s;
}
main()
{
int i = 5;
DEBUG("The value is: " << i << endl); // This doesn't compile
DEBUG("The value is: " + i + endl); // Neither does this
}
I found similar questions on here, but they all involve passing the stream object as a parameter, whereas I'm trying to pass the "streamed data" to a function that already has the stream object, so it's the other way round. Is this even possible? I don't want to resort to explicit type conversions. I also found this question, but I really don't want to write a whole logger class if I can avoid it.
At the moment I'm implementing it as a macro, which works, but I'd rather use an inline function if possible.
#define DEBUG(s) (cout << s)
Of course it does not compile. There are many reasons for that.
First, Operator << is not defined for standard streams, and you are trying to do exactly that: stream stream into stream in your DEBUG(). (Pun intended).
Second, operator << is not defined for string literals, and you are trying to invoke it here:
"The value is: " << i
+ is not defined for literals either, by the way.
To achieve the semantic you want to see, you will have to start with the stream. String literal need to be converted to stream first, and than you can apply << to it. This is ONLY way to achieve what you want.
Edit:
Now since I understand the rationale, I can give a better answer. There are many ways how people are trying to segregate different levels of debugging uniformely, and there are several libraries aiming for that (log4cpp, boost.log to name just few). Before you start implementing your own logging, I would definitely suggest looking into those. There is much more to the good logging than just debug levels.
If, for any reason, you want to use your own homebrew, here are the couple of recepies you might explore:
Use your own logger class (one of the very rare examples, close to
the single one! where Singleton is appropriate). You can than set the
logging level in the beggining of your application, and than just
call Logger::debug() << ...
Enrich above solution with macros. The problem with functions is that, unlike macros, they loose context. So if you want to log file and line number of the logging invocation (and you usually do!), you might want to do LOG_DEBUG << ...; here LOG_DEBUG would expand into something like Logger::debug() << __FILE__ << ":" << __LINE__ << ....
Once you've done this, you will see that sometimes you call other functions inside the << chain. At this point you might realize that those functions would be called regardless of your debug level, and might think you do not want to call them when debugging is not enabled (something along the lines LOG_DEBUG << " Object now is " << object.serialize(); So you will want to enrich the LOG_DEBUG macro to not execute anything when debug level does not match.
And the saga continues... Ready to use the library?
Well, what (at least some) logging libraries would do is create a temporary proxy object that would act as a stream:
#include <iostream>
struct LoggerProxy {
LoggerProxy(const char* file, int line)
{
std::cout << "File " << file << ", line " << line << ": ";
}
template<typename T>
LoggerProxy& operator<<(T&& t)
{
std::cout << t;
return *this;
}
};
#define LOG_DEBUG LoggerProxy{__FILE__, __LINE__}
int main()
{
LOG_DEBUG << "Value is: " << 4;
}
You can do a lot of fancy stuff with this, such as debug level checks, output to different streams or multiple backends (such as simultaneous output to std::cout/cerr and log file) and many more.

Assert with dynamic message?

In my program I want to use asserts that show an error message. Apart from the well known workarounds for C and C++ there's the "real" solution as BOOST offers BOOST_ASSERT_MSG( expr, msg ) (see also assert() with message)
But a static message isn't enough for me, I also want to show sometimes the failed variables, e.g. in a case like
BOOST_ASSERT_MSG( length >= 0, "No positive length found! It is " << length )
As you can see I'd like to format the message "string" as an stringstream or ostream as that'd allow me to easily show custom types (assuming I've defined the relevant formating function).
The problem here is that BOOST_ASSERT_MSG is by default requiring a char const * so that's not compatible.
Is there a way to redefine / overload assertion_failed_msg() in such a way that using a stream as message will work? How?
(My naive approach failed as the compiler first wanted to do an operator<<("foo",bar) on the message itself...)
You could define your own macro
#define ASSERT_WITH_MSG(cond, msg) do \
{ if (!(cond)) { std::ostringstream str; str << msg; std::cerr << str.str(); std::abort(); } \
} while(0)
It's relatively trivial to achieve this.
BOOST_ASSERT_MSG( length >= 0, (std::stringstream() << "No positive length found! It is " << length).str().c_str() )
Here is a solution that doesn't rely on macros. Instead, it uses a tiny bit of templating and lambda syntax.
template<typename Fn>
void assert_fn( bool expr, Fn fn) {
if (!expr) {
fn();
abort();
}
}
The argument fn can be any callable.
For instance you can call it like so:
assert_fn( a==b, [&](){ cout << "Assertion failed: a="<< a <<
" is different from but b=" << b << endl; } );
The advantage is that the output is that you are not calling abort explicitly and the output is fully customizable. The this advantage, of course, are the seven extra characters of lambda function boilerplate: [&](){} )
I use the BOOST_ASSERT_MSG with my own wrapper around it, so that specifying the assert message with multiple operator<< seems less complex.
#if defined ASSERT_ENABLED
#define ASSERT(cond, msg) {\
if(!(cond))\
{\
std::stringstream str;\
str << msg;\
BOOST_ASSERT_MSG(cond, str.str().c_str());\
}\
}
#else
#define ASSERT(...)
#endif
usage example, provide custom message like you are outputting to cout:
ASSERT(execSize == (_oldSize - remaining), "execSize : " << execSize << ", _oldSize : " << _oldSize << ", remaining : " << remaining);
What it does is, if ASSERT_ENABLED is defined,enable the assertion messages. if(!(cond)) part is optimization, which avoids the costly string operations specified by macro parameter msg, if cond is true
If you are working on Windows only, you can take a look to assert macro. Under the hood it uses _wassert. You can write your own assert macro using it. For instance in my case if I get some point, I want to show assert without conditions:
#ifdef DEBUG
const std::wstring assert_msg = /* build the string here */;
_wassert(assert_msg.c_str(), _CRT_WIDE(__FILE__), (unsigned)(__LINE__));
#endif
I think on other OS you can do the same trick, just take look at assert macro.

cpp suggest better ways to go to silence state without overhead/io calls

We have daemon that can be run at silence mode and print mode (print to std::cout). How to make it silence without overhead and io calls. Suggest more better ways to do so! Or write what is the way is better! (advantages/disadvantage)
eg:
1 Way:
Simple place at the code std::cout << "blah-blah-blah: " << var << std::endl;
When need to go silence close(STDOUT_FILENO) or rewrite cout to dev/null (how?)
2 Way
Using global bool FLAG_SILENCE and check it before every cout calls: if (!FLAG_SILENCE) std::cout << "blah-blah-blah: " << var << std::endl;
3 Way
Predefined macros #define SILENTCOUT std::cout when need to be silence #define SILENTCOUT SOMETHING (something = some function that have operator << and without overhard(does not know how to realise, seems need to define our own function with defined<<` that do nothing )
4 Way
Predefined macro #define SILENTCOUT(x) std::cout << x << std::endl using SILENTCOUT( "mess" ) -- dangerous, very ugly
A common solution is to provide macros that enclose the if and the actual printing:
#define LOG( msg ) \
if ( !log_enabled ) {} else \
std::cout << msg;
Although in general the macros are a bit more complicated (for example, instead of testing log_enabled take a log level, compare it against a predefined level and log accordingly).
Some libraries use the option of a macro that returns a logger object that implements operator<< and depending on the configuration will provide either a proper logger or a no-op sink that just ignores the arguments. This might be slightly less performant as this requires at the very least the function calls to operator<<.
At any rate I suggest that you use a logging library, as these problems have already been resolved many times already.