我正在尝试使用“gcovr”获得代码覆盖率。我-O0
用作优化级别。对于线路覆盖,我得到了我需要的结果,但不幸的是分支覆盖没有。根据下面的答案,gcc 在编译时会产生额外的代码,这会影响程序中的分支数。有没有办法告诉gcc
不要生成额外的代码,或者至少生成尽可能少?
根据提到的答案,使用-O1
有助于生成更少的额外代码,但它并没有给我带来任何好处。相反,我得到了更多的行覆盖(这是错误的),而一个分支的覆盖更少。
我正在尝试使用“gcovr”获得代码覆盖率。我-O0
用作优化级别。对于线路覆盖,我得到了我需要的结果,但不幸的是分支覆盖没有。根据下面的答案,gcc 在编译时会产生额外的代码,这会影响程序中的分支数。有没有办法告诉gcc
不要生成额外的代码,或者至少生成尽可能少?
根据提到的答案,使用-O1
有助于生成更少的额外代码,但它并没有给我带来任何好处。相反,我得到了更多的行覆盖(这是错误的),而一个分支的覆盖更少。
GCC 的分支覆盖率统计取决于机器代码级别的分支,而不仅仅是源代码中明确的分支(if/else、switch/case、for、while、||、&&、?:、...)。编译器通常必须插入额外的分支来实现语言特性,尤其是在 C++ 中:
如果允许 GCC 进行优化,这也许可以消除其中一些分支。这就是为什么使用-O1
有时可以帮助处理覆盖数据。另一方面,这使得 gcov 更难以将覆盖率数据归因于正确的源代码行。
理论上可以采用所有机器代码分支。如果发现其中一个分支,则表示未测试的状态转换。从编译器的角度来看,if 语句或调用可以抛出的函数之间没有太大区别。但对你来说,这些并不等同:你可能只对测试显式分支感兴趣。
根据您的质量要求,这是一个合理的位置。如果没有故障注入等先进技术,就不可能彻底测试所有机器代码分支。我个人建议不要忽略编译器插入的分支,因为它给人一种错误的安全感。
因此,我们必须接受 50% 的分支覆盖率仅来自良好的语句覆盖率是免费的,但 100% 的分支覆盖率是无法实现的。在 C++ 的上下文中,最好使用分支覆盖率来查看逐行覆盖率,而不是作为汇总统计数据。
GCC 确实允许您通过使用-fno-exceptions
标志编译软件而不进行异常处理。该进程不会抛出异常,而是直接中止。但这有效地将您切换到不兼容的 C++ 方言。try/catch 之类的东西将不再起作用;标准库更改中的错误检查。因此,仅出于代码覆盖的目的,您不能毫无例外地编译您的软件。
幸运的是,GCC 标记了为异常处理而添加的分支。自 gcovr 4.2(尚未发布)以来,您可以使用该gcov --exclude-throw-branches
标志来忽略未发现的仅异常分支。这并不完美:它不仅排除了某些异常处理板的隐式分支,而且还排除了显式catch
子句的分支。这可能会隐藏您确实想要测试的未覆盖的未覆盖。
Gcovrs 也提供了这个--exclude-unreachable-branches
选项。如果它们归因于似乎不包含有用代码的行,这将删除分支覆盖数据。同样,这可能会排除重要的覆盖率数据,例如,如果多行语句的覆盖率归因于不包含有用代码的行。但是,这通常有助于排除由于静态变量而插入的分支。