在C ++中编写调试模式的标准方法

时间:2015-02-26 08:40:37

标签: c++ debugging

在一个代码中,在调试模式下编码是否有“最佳实践”或类似内容? 例如,

#include <iostream>

int main()
{
    #ifdef MY_DEBUG_DEF
    std::cout << "This is only printed if MY_DEBUG_DEF is defined\n";
    #endif

    return 0;
}

或者这被认为是不好的做法,因为代码变得有点麻烦? 我注意到一些库(例如libcurl,这是一个大而着名的库)具有此功能;如果使用libcurl定义VERBOSE,则基本上可以获得调试模式

谢谢。

4 个答案:

答案 0 :(得分:3)

更常用的方法是遵循assert(3)中的约定:包含#ifndef NDEBUG .... #endif代码,该代码仅对调试有用,且没有任何明显的副作用。< / p>

您甚至可以添加一些调试打印宏,如

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

并在代码中的适当位置使用OUTDEBUG("x=" << x)之类的内容。然后通过调试器或通过一些程序参数设置wantdebug标志。您可能希望发出换行符并刷新cerr(或cout或您自己的调试输出流) - 使用std::endl ...-以立即显示调试输出(所以a你程序的未来崩溃仍然会提供合理的调试输出。)

答案 1 :(得分:1)

这是一种可接受的方法。是的,它变得混乱,但它也使调试更容易。此外,你通常可以摧毁这些东西,从而消除混乱。

正如您所提到的,libcurl使用该方法。我曾经有一位老师在他们的打印机软件上为惠普工作,他们使用相同的方法。

答案 2 :(得分:0)

我个人更喜欢启用运行时的日志记录。这意味着您不必重新编译以获得&#34;调试输出&#34;。所以我有一个命令行参数-v=n,其中n默认为零,并存储在实际程序中的变量verbosity中。使用-v=1我得到基本的跟踪(代码的基本流程),-v=2我得到了更多东西&#34; (例如在所选函数中转储内部状态)。两个级别通常是足够的,但有时三个级别可能是好的。另一种方法是使verbosity为位模式,并根据设置的位启用/禁用某些功能 - 因此设置bit 0进行基本跟踪,bit 1在某些模块中提供额外信息,第2位在另一个模块中提供了额外的跟踪等。如果您想要真正的想象,那么您有名称,例如-trace=all_basic-trace=detailed-trace=module_A-trace=all_basic,module_A,module_B或一些这样的。

将此与宏结合起来:

 #define TRACE do { if (verbosity > 0) \ 
       std::cout << __FILE__ << ":" << __LINE__ << ":" \
                 << __PRETTY_FUNCTION__ << std::endl; } while(0)

对于可能需要大量额外时间的事情,例如验证大型复杂数据结构(树,链表等)的正确性,然后围绕该代码使用#ifndef NDEBUG将是一件好事事情。当然,假设你相信你永远不会在发布版本中搞砸了。

真实的livig代码: https://github.com/Leporacanthicus/lacsap/blob/master/trace.h https://github.com/Leporacanthicus/lacsap/blob/master/trace.cpp 在这里使用例如: https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp

(请注意,一些被称为很多的简单函数没有&#34; TRACE&#34; - 它只会使跟踪混乱并使其太长)

答案 3 :(得分:-1)

使用记录器可能会更好,例如

以上非常灵活,但重量级。您也可以实现一些简单的宏:

#ifdef NDEBUG
#define DBG(FMT, ...)
#else // !NDEBUG
#define DBG(FMT, ...) fprintf (stderr, FMT, ## __VA_ARGS__)
#endif // NDEBUG

以上是来自Macros with a Variable Number of Arguments.的GCC语法 对于VC,请参阅How to make a variadic macro (variable number of arguments)