如何分离调试和释放模式代码

时间:2010-03-24 15:00:56

标签: c++ c debugging visual-studio-2005

在调试模式或我正在进行测试时,我需要打印大量各种信息,所以我使用这种方法:

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

这是一个好方法,还是有其他简单而优雅的方法?

但是这样,我在两个地方重复相同的代码,如果稍后要在代码中进行更改,我必须在两个地方都这样做,这很费时且容易出错。

感谢。

我正在使用MS Visual Studio。

7 个答案:

答案 0 :(得分:17)

您可以使用宏来打印调试信息,然后在发布版本中将该宏定义为空。

如,

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

使用此方法,您还可以添加更多信息,例如

__LINE__ 
__FILE__

自动调试信息。

答案 1 :(得分:6)

写一次

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

然后

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
}

答案 2 :(得分:2)

在包含标题

上使用类似的定义
#ifdef  TESTING
#define DEBUG_INFOS(_X_) CallYourDebugFunction(_X_ )
#else
#define DEBUG_INFOS(_X_) ((void)0)
#endif

然后在代码上只使用它

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

您还可以使用和搜索 ASSERT TRACE 宏,并使用sysinternals中的 DebugView 从跟踪中读取输出实时,或跟踪ASSERT的问题。 ASSERT和TRACE做类似的工作,你可以从中获得想法。

评论:我使用TESTING声明,因为我在问题上看到了这一点。

答案 3 :(得分:2)

使用Log4Cxx,而不是滚动自己的日志记录。 Log4Cxx包是高度可配置的,支持基于重要性/严重性的不同级别的日志记录,并支持多种形式的输出。

此外,除非必须进行超级优化的非常关键的代码,否则我建议在代码中保留日志记录语句(假设您使用Log4Cxx),但只需调低日志记录级别。这样,可以动态启用日志记录,如果您的某个用户遇到难以复制的错误,这可能会非常有用......只需指导他们如何配置更高的日志记录级别。如果您完全忽略了可执行文件的日志记录,那么就无法在该字段中获得有价值的调试输出。

答案 4 :(得分:1)

您可以使用类似boost::log设置严重程度级别的内容。

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";
}

我认为pantheios也有类似的东西。

答案 5 :(得分:0)

我正在用C编写嵌入式系统。 在我的程序中,我正在使用以下宏:

#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)

当我发布版本时,我只需关闭#define DEBUG指令,所有宏都会变空。 请注意,它不会消耗发行版中的任何CPU周期和内存。 宏是保存日志信息的唯一方法:记录完成的位置 (文件和行号)。

如果我需要这些信息,我会使用: _L;_LS("this is a log message number ");_LI(5);

否则没有_L指令。

答案 6 :(得分:0)

有一种简单的方法,适用于大多数编译器:

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

接下来,在源代码中,您应该将其用作:

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

缺点是你必须使用双括号,但在旧的C和C ++中 标准variadic宏不受支持(仅作为编译器扩展)。