Is there a "best practice" or similar for coding in a debug-mode in one's code?
For example,
#include <iostream>
int main()
{
#ifdef MY_DEBUG_DEF
std::cout << "This is only printed if MY_DEBUG_DEF is defined\n";
#endif
return 0;
}
Or is this considered bad practice because the code gets bit messier?
I have noticed some libraries (for example libcurl, which is a large and well-known library) have this feature; if you define VERBOSE with libcurl you get basically a debug mode
Thank you.
A more usual way is to follow conventions from assert(3): wrap with #ifndef NDEBUG .... #endifcode which is only useful for debugging, and without any significant side effects.
You could even add some debug-printing macro like
extern bool wantdebug;
#ifndef NDEBUG
#define OUTDEBUG(Out) do { if (wantdebug) \
std::cerr << __FILE__ << ":" << __LINE__ \
<< " " << Out << std::endl; \
} while(0)
#else
#define OUTDEBUG(Out) do {}while(0)
#endif
and use something like OUTDEBUG("x=" << x) at appropriate places in your code. Then wantdebug flag would be set thru the debugger, or thru some program arguments. You probably want to emit a newline and flush cerr (or cout, or your own debug output stream) -using std::endl ...- to get the debug output displayed immediately (so a future crash of your program would still give sensible debug outputs).
That is an acceptable method. Yes, it gets messy, but it makes it a lot easier to debug as well. Plus you can normally collapse those kinds of things, thus removing the messiness.
As you've mentioned, libcurl uses the method. I also used to have a teacher who works for HP on their printer software, and they used the same method.
I personally prefer runtime enabled logging. That means that you don't have to recompile to get the "debug output". So I have a command-line argument -v=n, where n defaults to zero, and gets stored in the variable verbosity in the actual program. With -v=1 I get basic tracing (basic flow of the code), with -v=2 I get "more stuff" (such as dumps of internal state in selected functions). Two levels is often enough, but three levels may be good at times. An alternative is to make verbosity a bit-pattern, and enable/disable certain functionality based on which bits are set - so set bit 0 for basic trace, bit 1 gives extra info in some module, bit 2 gives extra trace in another module, etc. If you want to be REALLY fancy, you have names, such as -trace=all_basic, -trace=detailed, -trace=module_A, -trace=all_basic,module_A,module_B or some such.
Combine this with a macro along the lines of:
#define TRACE do { if (verbosity > 0) \
std::cout << __FILE__ << ":" << __LINE__ << ":" \
<< __PRETTY_FUNCTION__ << std::endl; } while(0)
For things that may take a substantial amount of extra time, such as verifying the correctness of a large and complex data structure (tree, linked list, etc), then using #ifndef NDEBUG around that code would be a good thing. Assuming of course you believe that you'll never mess that up in a release build.
Real livig code here:
https://github.com/Leporacanthicus/lacsap/blob/master/trace.h
https://github.com/Leporacanthicus/lacsap/blob/master/trace.cpp
being use here for example:
https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp
(Note that some simple functions that get called a lot don't have "TRACE" - it just clutters up the trace and makes it far too long)
Using logger may be better, e.g.
log4cxx
log4cpp
ACE_Log_Msg: It is in ACE
Boost.Log:
The above are very flexible, but heavyweight. You can also implement some simple macros instead:
#ifdef NDEBUG
#define DBG(FMT, ...)
#else // !NDEBUG
#define DBG(FMT, ...) fprintf (stderr, FMT, ## __VA_ARGS__)
#endif // NDEBUG
The above is GCC syntax from Macros with a Variable Number of Arguments.
For VC, please see also How to make a variadic macro (variable number of arguments)
Related
In my VC++ project I use a macro for debugging and logging purpose.
calling:
Logger(LogLevel::Info, "logging started");
macro:
#ifdef DEBUG
#define Logger(level, input) \
{ \
cerr << "[" << level << "] " << input << endl; \
};
#else
#define Logger();
#endif
When compiling this I get the following warning (but it still compiles):
warning C4002: too many actual parameters for macro 'Logger'
I am wondering how the compiler handles this situation.
Are the macro parameters still used for compiling? E.g. will one be able to see the "logging started" string on reverse engeneering?
I am wondering how the compiler handles this situation. Are the macro parameters still used for compiling?
Macros are processed in the pre-processing stage. If the pre-processor is able to deal with the extra arguments used in the usage of the macro, the only thing it can do is drop those parameters in the macro expansion.
E.g. will one be able to see the "logging started" string on reverse engeneering?
No, the code processed by the compiler will not have that line at all.
If you have the option to change those lines of code, I would recommend changing the non-debug definition of the macro to be a noop expansion. E.g.:
#define Logger(level, input) (void)level;
As per the law, a macro function must declare as many parameters as you call it with.
So calling your macro
#define Logger()
as Logger(LogLevel::Info, "logging started") results in an error. MSVC probably allows it because it isn't standard-compliant. There's not much to reason further (which is my answer to the actual question).
You either
#define Logger(unused,unused2)
and leave the replacement part empty or
#define Logger(...)
and suffer the consequences of being able to call with any number of arguments. [Hint: First one is recommended.]
I often find myself writing a code that looks something like this:
if(a == nullptr) throw std::runtime_error("error at " __FILE__ ":" S__LINE__);
Should I prefer handling errors with if unlikely?
if unlikely(a == nullptr) throw std::runtime_error("error at " __FILE__ ":" S__LINE__);
Will the compiler automatically deduce which part of the code should be cached or is this an actually useful thing to do? Why do I not see many people handling errors like this?
Yes you can do that. But even better is to move the throw to a separate function, and mark it with __attribute__((cold, noreturn)). This will remove the need to say unlikely() at each call site, and may improve code generation by moving the exception throwing logic entirely outside the happy path, improving instruction cache efficiency and inlining possibilities.
If you prefer to use unlikely() for semantic notation (to make the code easier to read), that's fine too, but it isn't optimal by itself.
Should I use "if unlikely" for hard crashing errors?
For cases like that I'd prefer moving code that throws to a standalone extern function that's marked as noreturn. This way, your actual code isn't "polluted" with lots of exception-related code (or whatever your "hard crashing" code). Contrary to the accepted answer, you don't need to mark it as cold, but you really need noreturn to make compiler not to try generating code to preserve registers or whatever state and essentially assume that after going there there is no way back.
For example, if you write code this way:
#include <stdexcept>
#define _STR(x) #x
#define STR(x) _STR(x)
void test(const char* a)
{
if(a == nullptr)
throw std::runtime_error("error at " __FILE__ ":" STR(__LINE__));
}
compiler will generate lots of instructions that deal with constructing and throwing this exception. You also introduce dependency on std::runtime_error. Check out how generated code will look like if you have just three checks like that in your test function:
First improvement: to move it to a standalone function:
void my_runtime_error(const char* message);
#define _STR(x) #x
#define STR(x) _STR(x)
void test(const char* a)
{
if (a == nullptr)
my_runtime_error("error at " __FILE__ ":" STR(__LINE__));
}
this way you avoid generating all that exception related code inside your function. Right away generated instructions become simpler and cleaner and reduce effect on the instructions that are generated by your actual code where you perform checks:
There is still room for improvement. Since you know that your my_runtime_error won't return you should let the compiler know about it, so that it wouldn't need to preserve registers before calling my_runtime_error:
#if defined(_MSC_VER)
#define NORETURN __declspec(noreturn)
#else
#define NORETURN __attribute__((__noreturn__))
#endif
void NORETURN my_runtime_error(const char* message);
...
When you use it multiple times in your code you can see that generated code is much smaller and reduces effect on instructions that are generated by your actual code:
As you can see, this way compiler doesn't need to preserve registers before calling your my_runtime_error.
I would also suggest against concatenating error strings with __FILE__ and __LINE__ into monolithic error message strings. Pass them as standalone parameters and simply make a macro that passes them along!
void NORETURN my_runtime_error(const char* message, const char* file, int line);
#define MY_ERROR(msg) my_runtime_error(msg, __FILE__, __LINE__)
void test(const char* a)
{
if (a == nullptr)
MY_ERROR("error");
if (a[0] == 'a')
MY_ERROR("first letter is 'a'");
if (a[0] == 'b')
MY_ERROR("first letter is 'b'");
}
It may seem like there is more code generated per each my_runtime_error call (2 more instructions in case of x64 build), but the total size is actually smaller, as the saved size on constant strings is way larger than the extra code size.
Also, note that these code examples are good for showing benefit of making your "hard crashing" function an extern. Need for noreturn becomes more obvious in real code, for example:
#include <math.h>
#if defined(_MSC_VER)
#define NORETURN __declspec(noreturn)
#else
#define NORETURN __attribute__((noreturn))
#endif
void NORETURN my_runtime_error(const char* message, const char* file, int line);
#define MY_ERROR(msg) my_runtime_error(msg, __FILE__, __LINE__)
double test(double x)
{
int i = floor(x);
if (i < 10)
MY_ERROR("error!");
return 1.0*sqrt(i);
}
Generated assembly:
Try to remove NORETURN, or change __attribute__((noreturn)) to __attribute__((cold)) and you'll see completely different generated assembly!
As a last point (which is obvious IMO and was omitted). You need to define your
my_runtime_error function in some cpp file. Since it's going to be one copy only, you can put whatever code you want in this function.
void NORETURN my_runtime_error(const char* message, const char* file, int line)
{
// you can log the message over network,
// save it to a file and finally you can throw it an error:
std::string msg = message;
msg += " at ";
msg += file;
msg += ":";
msg += std::to_string(line);
throw std::runtime_error(msg);
}
One more point: clang actually recognizes that this type of function would benefit from noreturn and warns about it if -Wmissing-noreturn warning was enabled:
warning: function 'my_runtime_error' could be declared with attribute
'noreturn' [-Wmissing-noreturn] { ^
It depends.
First of all, you can definitely do this, and this will likely (pun intended) not harm the performance of your application. But please note that likely/unlikely attributes are compiler-specific, and should be decorated accordingly.
Secondly, if you want a performance gain, the outcome will depend on the target platform (and corresponding compiler backend). If we're talking about the 'default' x86 architecture, you will not get much of a profit on modern chips - the only change these attributes will produce is a change in the code layout (unlike earlier times when x86 supported software branch prediction). For small branches (like your example), it will have very little effect on cache utilization and/or front-end latencies.
UPDATE:
Will the compiler automatically deduce which part of the code should be cached or is this an actually useful thing to do?
This is actually a very wide and complicated topic. What will compiler do depends on the particular compiler, its backend (target architecture) and compilation options. Again, for x86, here's the following rule (taken from IntelĀ® 64 and IA-32 Architectures Optimization Reference Manual):
Assembly/Compiler Coding Rule 3. (M impact, H generality) Arrange code to be consistent with
the static branch prediction algorithm: make the fall-through code following a conditional branch be the
likely target for a branch with a forward target, and make the fall-through code following a conditional
branch be the unlikely target for a branch with a backward target.
As far as I'm aware, that's the only thing that's left from static branch prediction in modern x86, and likely/unlikely attributes might only be used to "overwrite" this default behaviour.
Since you're "crashing hard" anyways, I'd go with
#include <cassert>
...
assert(a != nullptr);
This is compiler-independent, should give you close to optimal performance, gives you a breakpoint when running in a debugger, generates a core dump when not in a debugger, and can be disabled by setting the NDEBUG preprocessor symbol, which many build systems do by default for release builds.
I would have assumed this would be a widely asked question, but still I have yet to find an answer.
I was debugging some C++ code that was creating errors in a subtle way only with certain function handles as inputs. Long story short fixed the problem but I defined in the .cpp file:
#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)
needless to say the code is littered with:
DEBUG("Foo's address")
DEBUG(&Foo)
Now I assumed that in "Release" that the compiler would ignore all these pre-compiler outputs. But it doesn't!
So how does one do this in practice (I want to leave the outputs for future additions, but obviously don't want it in release versions)? I'm trying out clion which uses cmake, is this something IDE/compiler specific?
Thanks
Depending on your compiler it may define something that tells you that compilation is in debug mode (or you can do that yourself on the command line), then:
#ifndef _DEBUG // works in VS
#define DEBUG(x)
#else
#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)
#endif
For more discussion on which macro to use, see this question.
Portable way of doing this would be using NDEBUG
#ifdef NDEBUG
#define DEBUG(x)
#else
#define DEBUG(x) do { std::cerr << x << std::endl; } while (0)
#endif
See: C / C++ : Portable way to detect debug / release?
It is usually a mistake to eliminate logging messages in so-called "release versions". After all, "release versions" are where you will need the logged information most! How else will you even hope to analyse and fix the problem when the end user will tell you nothing but "it doesn't work" or "it crashed"?
So instead of eliminating the valuable information that your software creates to aid you in your bugfixing sessions, think about how to save and persist it such that it can be easily transmitted to you by the end user if problems arise. Like, redirecting the log messages to a log file when the application runs on the user's machine (perhaps with the application itself offering a "Send log file to support" feature, or something like that).
Code like
DEBUG("Foo's address")
DEBUG(&Foo)
should be replaced with something like:
Log("Foo's address");
Log(std::to_string(&Foo));
Then inside of your Log function, which may have a signature like void Log(std::string const& message), you can check your DEBUG macro and act accordingly:
void Log(std::string const& message)
{
#ifdef DEBUG
// write message to std::cerr
#else
// write message to log file
#endif
}
Now, of course, DEBUG is not a standard macro (unlike NDEBUG, which turns assert on and off). It's not implicitly defined. You have to define it yourself when you invoke your compiler. For example, /DDEBUG with MSVC or -DDEBUG with GCC. Chances are that your IDE adds such a flag, or something similar like -D_DEBUG when it runs the compiler, but still, that's not standard and not part of the compiler itself. (Actually, you might consider a different name for the macro anyway if you are going to use it like this, something like LOG_TO_CONSOLE.)
In any case, this is just to give you an inspiration of what do do. You may prefer a std::ostream-based approach instead of a function taking a std::string. There are a lot of questions and answers on Stackoverflow about this.
The important point is: Don't throw away valuable log information under the assumption that you won't need it once your software is released. There will be bugs and vague error descriptions.
I'd like to have the possibility to increase the verbosity for debug purposes of my program. Of course I can do that using a switch/flag during runtime. But that can be very inefficient, due to all the 'if' statements I should add to my code.
So, I'd like to add a flag to be used during compilation in order to include optional, usually slow debug operations in my code, without affecting the performance/size of my program when not needed. here's an example:
/* code */
#ifdef _DEBUG_
/* do debug operations here
#endif
so, compiling with -D_DEBUG_ should do the trick. without it, that part won't be included in my program.
Another option (at least for i/o operations) would be to define at least an i/o function, like
#ifdef _DEBUG_
#define LOG(x) std::clog << x << std::endl;
#else
#define LOG(x)
#endif
However, I strongly suspect this probably isn't the cleanest way to do that. So, what would you do instead?
I prefer to use #ifdef with real functions so that the function has an empty body if _DEBUG_ is not defined:
void log(std::string x)
{
#ifdef _DEBUG_
std::cout << x << std::endl;
#endif
}
There are three big reasons for this preference:
When _DEBUG_ is not defined, the function definition is empty and any modern compiler will completely optimize out any call to that function (the definition should be visible inside that translation unit, of course).
The #ifdef guard only has to be applied to a small localized area of code, rather than every time you call log.
You do not need to use lots of macros, avoiding pollution of your code.
You can use macros to change implementation of the function (Like in sftrabbit's solution). That way, no empty places will be left in your code, and the compiler will optimize the "empty" calls away.
You can also use two distinct files for the debug and release implementation, and let your IDE/build script choose the appropriate one; this involves no #defines at all. Just remember the DRY rule and make the clean code reusable in debug scenario.
I would say that his actually is very dependent on the actual problem you are facing. Some problems will benefit more of the second solution, whilst the simple code might be better with simple defines.
Both snippets that you describe are correct ways of using conditional compilation to enable or disable the debugging through a compile-time switch. However, your assertion that checking the debug flags at runtime "can be very inefficient, due to all the 'if' statements I should add to my code" is mostly incorrect: in most practical cases a runtime check does not influence the speed of your program in a detectable way, so if keeping the runtime flag offers you potential advantages (e.g. turning the debugging on to diagnose a problem in production without recompiling) you should go for a run-time flag instead.
For the additional checks, I would rely on the assert (see the assert.h) which does exactly what you need: check when you compile in debug, no check when compiled for the release.
For the verbosity, a more C++ version of what you propose would use a simple Logger class with a boolean as template parameter. But the macro is fine as well if kept within the Logger class.
For commercial software, having SOME debug output that is available at runtime on customer sites is usually a valuable thing to have. I'm not saying everything has to be compiled into the final binary, but it's not at all unusual that customers do things to your code that you don't expect [or that causes the code to behave in ways that you don't expect]. Being able to tell the customer "Well, if you run myprog -v 2 -l logfile.txt and do you usual thing, then email me logfile.txt" is a very, very useful thing to have.
As long as the "if-statement to decide if we log or not" is not in the deepest, darkest jungle in peru, eh, I mean in the deepest nesting levels of your tight, performance critical loop, then it's rarely a problem to leave it in.
So, I personally tend to go for the "always there, not always enabled" approach. THat's not to say that I don't find myself adding some extra logging in the middle of my tight loops sometimes - only to remove it later on when the bug is fixed.
You can avoid the function-like macro when doing conditional compilation. Just define a regular or template function to do the logging and call it inside the:
#ifdef _DEBUG_
/* ... */
#endif
part of the code.
At least in the *Nix universe, the default define for this kind of thing is NDEBUG (read no-debug). If it is defined, your code should skip the debug code. I.e. you would do something like this:
#ifdef NDEBUG
inline void log(...) {}
#else
inline void log(...) { .... }
#endif
An example piece of code I use in my projects. This way, you can use variable argument list and if DEBUG flag is not set, related code is cleared out:
#ifdef DEBUG
#define PR_DEBUG(fmt, ...) \
PR_DEBUG(fmt, ...) printf("[DBG] %s: " fmt, __func__, ## __VA_ARGS__)
#else
#define PR_DEBUG(fmt, ...)
#endif
Usage:
#define DEBUG
<..>
ret = do_smth();
PR_DEBUG("some kind of code returned %d", ret);
Output:
[DBG] some_func: some kind of code returned 0
of course, printf() may be replaced by any output function you use. Furthermore, it can be easily modified so additional information, as for example time stamp, is automatically appended.
For me it depends from application to application.
I've had applications where I wanted to always log (for example, we had an application where in case of errors, clients would take all the logs of the application and send them to us for diagnostics). In such a case, the logging API should probably be based on functions (i.e. not macros) and always defined.
In cases when logging is not always necessary or you need to be able to completely disable it for performance/other reasons, you can define logging macros.
In that case I prefer a single-line macro like this:
#ifdef NDEBUG
#define LOGSTREAM /##/
#else
#define LOGSTREAM std::clog
// or
// #define LOGSTREAM std::ofstream("output.log", std::ios::out|std::ios::app)
#endif
client code:
LOG << "Initializing chipmunk feeding module ...\n";
//...
LOG << "Shutting down chipmunk feeding module ...\n";
It's just like any other feature.
My assumptions:
No global variables
System designed to interfaces
For whatever you want verbose output, create two implementations, one quiet, one verbose.
At application initialisation, choose the implementation you want.
It could be a logger, or a widget, or a memory manager, for example.
Obviously you don't want to duplicate code, so extract the minimum variation you want. If you know what the strategy pattern is, or the decorator pattern, these are the right direction. Follow the open closed principle.
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.)
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.
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.