如何在宏中排除lcov分支

6

我的代码中有一些类似以下的日志宏:

#define LOG_MSG (pri, msg, ... ) \
    if (pri > PriorityLevel ) \
        printf( msg, ##\__VA_ARGS__);

我知道可以使用LCOV_EXCL_START,LCOV_EXCL_STOP或LCOV_EXCL_LINE来禁止一个分支。但如果我想在宏中包含这个注释,那么它只有在每次调用LOG_MSG时才能起作用:
LOG_MSG(ERROR, "An Error has occurred\n");//LCOV_EXCL_LINE
但是,如果我把这个注释放在宏里面,LCOV就不能识别它。例如,下面的代码仍然会产生分支。
#define LOG_MSG (pri, msg, ... ) \
    if (pri > PriorityLevel ) \
        printf( msg, ##\__VA_ARGS__);//LCOV_EXCL_LINE

有没有一种好的方法在宏中自行压缩这些分支?

如果pri是一个常量,编译器足够聪明,你不需要做任何这样的事情 :-/ - IdeaHat
宏定义有点复杂。PriorityLevel不是常量,可以在运行时更改。实际的宏定义还包括对Enabled常量的检查。当其为false时,if语句会被优化掉。但这只适用于发布代码。我想我可以尝试使用Release、Debug和CodeCoverage配置。覆盖率是一个禁用日志记录的调试构建。 - perogiex
这个问题也已经在Github上报告了:https://github.com/linux-test-project/lcov/issues/44 - dpi
5个回答

3
新版的lcov 1.11(或1.12)引入了LCOV_EXCL_BR_LINE关键字。因此在您的情况下:
LOG_MSG(ERROR, "An Error has occurred\n"); //LCOV_EXCL_BR_LINE

或者,更好的选择是:
LOG_MSG(ERROR, "An Error has occurred\n"); (void)("LCOV_EXCL_BR_LINE");

这个可以在预编译时保留注释。


这个注释被剥离的条件是什么?是 cpp 在执行这个操作吗? - jdpipe
在“翻译阶段”中,注释被替换为单个空格,这发生在预处理指令解析之前。VC++和GNU C编译器都遵循这种范例。 - tutejszy

2
为什么不将宏转换为函数?
例如:
template <typename ... Ts>
void LOG_MSG(int priority, const std::string& message, Ts&&...ts)
{
    if (priority > PriorityLevel)
        printf(message.c_str(), std::forward<Ts>(ts)...);
    // Or more appropriate stuff
}

我已将其制作为宏,这样当代码进入生产环境时,可以通过重新定义该宏为无操作来关闭日志记录。 - perogiex
一旦代码进入函数,您可以添加任何抑制机制(如//LCOV_EXCL_LINE)。然后,您可以创建调用该函数的宏(因此请调整名称)。 - Jarod42
如果您正在使用具有运行时配置的日志记录系统,那么除非您愿意为未启用的级别或记录器评估所有日志消息表达式,否则最少会在宏中有一个分支。 - washley
@perogiex实际上,如果任何一个表达式在调试模式下具有副作用,因为它正在被记录,那么no-op并不总是一个好主意。使用如此呈现的函数,您可以轻松设置“PriorityLevel”为“std::numeric_limits< decltype(PriorityLevel)>::max()”,并且如果优先级小于或等于限制(即总是在限制为“max()”时),立即退出。 - Alexis Wilke

2

我不知道如何在答案中添加代码,但这是对@Jarod42解决方案的回应。我没有使用C++0x,所以我对他的解决方案进行了一些修改:

void LogMsgFunc( U32 pri, const char* msg, ... )
{
    //LCOV_EXCL_START
    va_list variableArgumentList;
    va_start( variableArgumentList, msg );
    if ( pri <= PriorityLevel ) 
    { 
        vfprintf( stderr, msg, variableArgumentList );
    }    
    va_end( variableArgumentList );
    //LCOV_EXCL_STOP
}

#define LOG_MSG (pri, msg, ... ) \
    LogMsgFunc(pri, msg, ##__VA_ARGS__);

0

怎么样?

#define LOG_MSG__LCOV_EXCL_BR_LINE LOG_MSG

然后,您可以使用新的宏LOG_MSG__LCOV_EXCL_BR_LINE替换任何不需要覆盖测试的LOG_MSG调用。这样行得通吗?


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接