C ++动态启用/禁用std :: couts的调试消息

时间:2010-07-30 12:50:56

标签: c++ debugging

有没有办法在程序内部使用std :: cout定义/取消定义调试消息?

我知道有像#define,#ifnf这样的东西,但是我觉得有一个更简洁的方法让变量说:

# debug ON

打印我的所有调试数据(使用std :: cout)。因此,我们将为调试提供类似的代码:

#ifndef DEBUG
// do something useful
#endif

当你编写100多个调试代码时,我发现上面的代码很麻烦。

谢谢!

卡罗

9 个答案:

答案 0 :(得分:32)

#ifdef DEBUG
#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif

int main()
{
    DEBUG_MSG("Hello" << ' ' << "World!" << 1 );
    return 0;
}

答案 1 :(得分:7)

除非您有复杂的日志记录需求,否则某些日志库非常重要。这是我刚碰到的东西。需要进行一些测试,但可能符合您的要求:

#include <cstdio>
#include <cstdarg>

class CLog
{
public:
    enum { All=0, Debug, Info, Warning, Error, Fatal, None };
    static void Write(int nLevel, const char *szFormat, ...);
    static void SetLevel(int nLevel);

protected:
    static void CheckInit();
    static void Init();

private:
    CLog();
    static bool m_bInitialised;
    static int  m_nLevel;
};

bool CLog::m_bInitialised;
int  CLog::m_nLevel;

void CLog::Write(int nLevel, const char *szFormat, ...)
{
    CheckInit();
    if (nLevel >= m_nLevel)
    {
        va_list args;
        va_start(args, szFormat);
        vprintf(szFormat, args);
        va_end(args);
    }
}
void CLog::SetLevel(int nLevel)
{
    m_nLevel = nLevel;
    m_bInitialised = true;
}
void CLog::CheckInit()
{
    if (!m_bInitialised)
    {
        Init();
    }
}
void CLog::Init()
{
    int nDfltLevel(CLog::All);
    // Retrieve your level from an environment variable, 
    // registry entry or wherecer
    SetLevel(nDfltLevel);
}

int main()
{
    CLog::Write(CLog::Debug, "testing 1 2 3");
    return 0;
}

答案 2 :(得分:5)

可能不是。我建议使用日志库。我不确定C ++的最佳选择是什么,但我过去使用log4cpp并发现它非常好。

编辑:我假设在运行中意味着@运行时。如果您只需要它是编译时标志,那么Gianni's answer可能最容易实现。日志库为您提供了很大的灵活性,并允许重新配置@ runtime。

答案 3 :(得分:3)

虽然问题很老,而且有一些好的答案,但我想发布一个解决方案。这就像Giannis的方法,但不同。而且,我使用std :: cerr而不是std :: cout,但你可以很快地改变它。

#ifdef DEBUG
#  include <iostream>
#  define DEBUG_LOG std::cerr

#else
class log_disabled_output {};
static log_disabled_output log_disabled_output_instance;

template<typename T>
log_disabled_output& operator << (log_disabled_output& any, T const& thing) { return any; }

#  define DEBUG_LOG log_disabled_output_instance 
#endif

int main() {
    int x=0815;
    DEBUG_LOG << "my message " << x << " " << x/M_PI << "\n";
};

现在您可以像输出流一样使用它。

注意:仅在使用iostream时才会包含cerr。如果您还没有包含,这将减少包含量。如果定义DEBUG,则使用cerr来打印错误。否则,静态实例化空类log_disabled_output,并将operator<<重载为任何类型。这里的事情是;如果禁用日志记录,聪明的编译器会注意到与流无关并优化整个&#34;行&#34;离开,所以如果DEBUG被禁用,你就不会有任何开销。

答案 4 :(得分:2)

我试图做同样的事情。经过一些研究,我开发了以下内容,它似乎有效。如果您发现任何错误,请发表评论。

ostream DbgMsg(NULL);
enum {
  DBGMSG_NONE,
  DBGMSG_DEFAULT,
  DBGMSG_VERBOSE
} DbgLvl = DBGMSG_DEFAULT;

ostream &DbgMsgDefault(ostream &stream) {
  return (DbgLvl>=DBGMSG_DEFAULT) ? cout : stream;
}

ostream &DbgMsgVerbose(ostream &stream) {
  return (DbgLvl>=DBGMSG_VERBOSE) ? cout : stream;
}

void main() {
   DbgMsg<<DbgMsgDefault<<"default:default"<<endl;
   DbgMsg<<DbgMsgVerbose<<"default:verbose"<<endl;
   DbgLvl = DBGMSG_NONE;
   DbgMsg<<DbgMsgDefault<<"none:default"<<endl;
}

答案 5 :(得分:1)

一件干净的事情就是使用cerr。

“cerr”基本上表现为“cout”,但总是刷新输出(顺便说一下,对于调试很有用)。如果您需要删除所有消息,可以使用简单的查找和替换(cerr into // cerr)注释掉所有cerr消息。

甚至可能有更好的方法来使用cerr并彻底地将其去活(它写入一个特殊的流,错误流,因此名称)。 我希望这会有所帮助。

答案 6 :(得分:1)

这是我使用的(使用VC ++) - 这里&#34; ##&#34;用于连接

#ifdef DEBUG 
#define pout cout 
#else
#define pout / ## / cout 
#endif 

对于其他编译器,请使用:

#ifdef DEBUG 
#define pout cout 
#else
#define pout 0 && cout 
#endif 

用法:

pout << "hello world" << endl; 

答案 7 :(得分:0)

另一个简单的解决方案涉及在调试模式下打开std::ostream cout引用,在非调试模式下打开/dev/null,如下所示:

在debug.h中:

extern std::ostream &dout;

在debug.c中

#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif

然后:

dout << "This is a debugging message";

当然,这只适用于/dev/null指向空设备的任何系统。由于此处dout引用是全局的,因此它非常类似于cout。通过这种方式,您可以将相同的流指向多个输出流,例如指向日志文件,具体取决于调试标志的值等。

答案 8 :(得分:0)

我正在寻找类似的示例,并在下面分享我的示例:

#include <iostream>
enum debug_option
{
    DEBUG_DISABLE,
    DEBUG_ENABLE
};

class debug
{
public:
    debug_option debug_state;

    debug() : debug_state(DEBUG_ENABLE) {} // constr
    debug(debug_option state) : debug_state(state) {} // constr

    template<typename T>
    debug & operator<< (T input)
    {
    if (this->debug_state == DEBUG_ENABLE)
        std::cout << input;
    return *this;
    }
};

int main()
{
    debug log, log_lev2(DEBUG_DISABLE);
    log << "print 1..\n" << 55 << " over\n";
    log.debug_state = DEBUG_DISABLE;
    log << "print 2..\n" << 3 << "over\n";
    log_lev2 << "print 3..\n" << 4 << "over\n";
    log_lev2.debug_state = DEBUG_ENABLE;
    log_lev2 << "print 5..\n";
    std::cout << "std::cout << print..\n";
    return 0;
}

总是欢迎提出更好的建议。