开发者

how to separate debug and release mode code

During debug mode or while I am doing testing, I need to print lots of various information, so i use this method:

#ifdef TESTING
// code with lots of debugging info
#else
// clean code only
#endif // TESTING`

Is this a good method, or is there any other simple and elegant method ?

But this way, I am repeating the same code in two places and if anything is t开发者_Python百科o be changed later on in the code, I have to do it in both places, which is time consuming and error prone.

Thanks.

I am using MS Visual Studio.


You could use a macro to print debug information and then in the release build, define that macro as empty.

e.g.,

#ifdef _DEBUG
#define DEBUG_PRINT(x) printf(x);
#else
#define DEBUG_PRINT(x)
#endif

Using this method, you can also add more information like

__LINE__ 
__FILE__

to the debug information automatically.


Write once

#ifdef _DEBUG 
const bool is_debig = true;
#else 
const bool is_debig = false;
#endif 

and then

template<bool debug>
struct TemplateDebugHelper {
   void PrintDebugInfo(const char* );
   void CalcTime(...);
   void OutputInfoToFile(...);
   /// .....
};

// Empty inline specialization
template<>
struct TemplateDebugHelper<false> {
   void PrintDebugInfo(const char* ) {} // Empty body
   void CalcTime(...) {} // Empty body
   void OutputInfoToFile(...) {} // Empty body
   /// .....
};

typedef TemplateDebugHelper<is_debug> DebugHelper;

DebugHelper global_debug_helper;

int main() 
{
   global_debug_helper.PrintDebugInfo("Info"); // Works only for is_debug=true
}


Use a define like that on include headers

#ifdef  TESTING
#define DEBUG_INFOS(_X_) CallYourDebugFunction(_X_ )
#else
#define DEBUG_INFOS(_X_) ((void)0)
#endif

and then use only this on your code

...
DEBUG_INFOS("infos what ever");
RestOfWork();
...

You can also use and search for the ASSERT and TRACE macros and use the DebugView from sysinternals to read the output real time from trace, or track problems with the ASSERT. ASSERT and TRACE do similar work, and you can get ideas from them.

comments: I use the TESTING declare, because I see that on the question.


Use Log4Cxx, instead of rolling your own logging. The Log4Cxx package is highly configurable, supports different levels of logging based on importance/severity, and supports multiple forms of output.

In addition, unless it is very critical code that must be super optimized, I would recommend leaving logging statements (assuming you use Log4Cxx) in your code, but simply turn down the logging level. That way, logging can be dynamically enabled, which can be incredibly helpful if one of your users experiences a hard-to-replicate bug... just direct them on how to configure a higher logging level. If you completely elide the logging from the executable, then there is no way to obtain that valuable debugging output in the field.


You could use something like boost::log setting severity level to the one you need.

void init()
{
    logging::core::get()->set_filter
    (
        flt::attr< logging::trivial::severity_level >("Severity") >= logging::trivial::info
    );
}

int main(int, char*[])
{
    init();

    BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
    BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
    BOOST_LOG_TRIVIAL(info) << "An informational severity message";
    BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
    BOOST_LOG_TRIVIAL(error) << "An error severity message";
    BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
}

I think pantheios have something similar too.


I'm writing for embedded systems in C. In my programs I'm using following macros:

#define _L  log_stamp(__FILE__, __LINE__)

#define _LS(a)  log_string(a)

#define _LI(a)  log_long(a)

#define _LA(a,l)  log_array(a,l)

#define _LH(a)  log_hex(a)

#define _LC(a)  log_char(a)

#define ASSERT(con) log_assert(__FILE__, __LINE__, con)

When I'm making release version, I simply switch off #define DEBUG directive and all macros become empty. Note that it doesn't consume any CPU cycles and memory in release version. Macros are the only way to save to log information: where the logging was done (file and line number).

If I need this information I use: _L;_LS("this is a log message number ");_LI(5);

otherwise without _L directive.


There is a simple way, which works with most compilers:

#ifdef TESTING
    #define DPRINTF( args )     printf args
#else
    #define DPRINTF( args )     ((void)0)
#endif

Next, in the source code you should use it as:

DPRINTF(("Debug: value a = %d, value b = %d\n", a, b));

The drawback is that you have to use double parentheses, but in old C and C++ standards variadic macro are not supported (only as a compiler extension).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜