如何使用宏在C ++中嵌入调试语句

时间:2012-08-10 16:46:39

标签: c++ logging macros

我正在编写一个程序,我想根据各种宏变量的值输出不同类型的调试信息(这样我就可以更改一个标志的值,然后导致写入不同级别的信息到屏幕)。

例如,假设我有以下代码将有关我的程序的信息打印到屏幕上(称为 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;

现在,还假设我有以下代码在屏幕上显示有关我的程序的不同信息(称为 D2 ):

cout << "best = [ best; "
     << visited.vec[visited.bestIndex].meanQALY() << "];\n" << endl;
space.displayConstraintsMATLAB(idx+1);

我希望能够在我的代码中的某些位置插入#D1#D2等语句,并让宏处理器用上面的代码块替换这些语句。

我该怎么做?

(如果宏不是理想的解决方案,我很高兴听到有关不同方法的建议。)

2 个答案:

答案 0 :(得分:1)

您可以制作一个为您调试的宏 - 例如:

#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

否则你可以创建一个调试函数,然后在该函数内部对#if def语句进行类似的检查,看看你想如何处理输入。函数版本具有更早的类型检测功能,因此当您尝试打印不可处理的内容(某些自定义对象)时,它会以更好的方式告诉您错误。此外,如果函数是无操作(在发布模式下没有内部),那么当存在任何优化标志时,编译器将丢弃函数调用,因此您不会因释放模式而在发布模式下支付任何额外费用。调试调用。

对于我自己的调试调用,我通常定义一个流运算符,就像std :: cout一样,将所有输入转换为字符串或char *,然后如果定义了DEBUG则将它们转换为调试函数,或者不打印任何内容。对于例外和日志记录,您可以使用不同级别的严重性(信息,警告,错误等)执行类似的度量标准。这往往使得在C ++中抛出调试代码变得容易,就像在更现代的语言中一样。

答案 1 :(得分:1)

在我看来,您正在寻找的是一个日志设施。查看some suggestions的此帖子。

为什么使用整个框架而不是宏?

问题是正确的日志记录比看起来更困难。有线程问题,会话,类和对象实例是您必须考虑的因素。此外,日志文件缓冲,翻转和压缩日志文件是您必须考虑的问题。您可能还希望登录网络或syslog(或两者)或数据库。正确地实施所有这些是很多工作。

Macros有什么好处吗?

当然!在我们的项目中,我们定义了一个名为LOG的宏,它包含对我们的日志框架的调用(我们正在使用log4cpp)。如果有一天我们设备移动到另一个框架,我们只需要在一个地方重新定义我们的LOG宏,而不是梳理整个代码库。这是有效的,因为大多数日志记录框架共享一个类似的接口,通常由日志级别和消息字符串组成。