在代码库中嵌入C调试代码(printfs)的最佳实践

时间:2015-07-27 23:47:31

标签: c debugging

我刚刚在C中编写了一个大型项目。我有很多调试代码(printfs和代码中没有的东西)。现在这些调试语句是一个性能开销,我想删除它们,但它们在将来出于故障排除的目的非常有帮助。将调试代码放在代码库中的最佳实践是什么?我有很多选择。

  1. 使用终端参数(比如说-d)来指定可执行文件是否应该以调试模式运行。优点是代码不会在以后更改。缺点是代码将满足条件,以检查程序是否处于调试模式

  2. 另一种解决方案是使用一些C宏进行调试。我不太明白这是如何工作的。如果您处于调试模式,似乎您将d_printf定义为printf,如果您不在,则定义为<!DOCTYPE html> <html> <head> <title>Animation test</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div class="animation-object"> <div class="animation-object__strip"> <img src="images/image1.png"> <!-- Bunch of images of sequence here --> </div> </div> </body> </html> 。但我想这将需要在每次从调试模式更改为非调试模式时重新编译代码。

  3. 经验丰富的C专业人士可以就最佳实践提供建议吗?

2 个答案:

答案 0 :(得分:3)

就个人而言,我喜欢打开调试而无需重新编译以启用调试的能力。

我通常有一个调试方法来检查命令行arg或环境变量并输出消息&lt; =给定的优先级。

e.g。

void debug(int level, char *msg)
{
    if (level <= currentDebugLevel) {
        printf("%s\n", msg); /* or to stderr, or to file
    }
}

您可以将其设为varargs func,这样您就可以使用printf

答案 1 :(得分:2)

最佳做法?不要将printf()fprintf()用于stdoutstderr重定向到文件,尤其是对于长期存在的进程。这些方法可以用于随意调试,但对于可能产生大量数据的长期进程而言,它们存在严重缺陷。

如果您对此类固定流或文件使用printf()fprintf(),则会绑定到这些文件,并且无法轻松将日志记录移动到其他文件,或者您不能完全移动数据流,具体取决于很多细节。因此,如果不重新启动进程,则无法将日志文件作为日志文件老化过程的一部分进行移动,如果文件填满磁盘空间,也无法截断或以其他方式删除该文件。

并且没有必要重新发明轮子。几乎每个操作系统都提供了一个设计的日志记录功能,可以扩展并满足日志文件可以与执行日志记录的进程分离的要求。 Unix / Linux系统提供syslog(或引擎盖下的rsyslog),Windows系统提供EventLog API。一旦您学会了如何使用和配置它们,它们比几乎任何附加日志记录产品更容易配置,编码和使用。

此外,使用调试输出中的__func____FILE____LINE__预定义值定义调试宏:

#define DEBUGLOG( level, ... ) \
do \
{ \
    if ( ( level ) < currentDebugLevel ) \
    { \
        debugFuncCall( ( level ), __func__, __FILE__, __LINE__, __VA_ARGS__ ); \
    } \
} \
while ( 0 )

这将提供非常有用的调试数据。您可以定义简单的调试宏,例如ENTER_METHOD( args...)EXIT_METHOD( retval )宏,它们在适当的调试级别允许您跟踪程序的所有内容。