我如何告诉 gcov 忽略不可命中的 C++ 行代码?
我正在使用 gcov 来测量 C++ 代码中的覆盖率。我希望达到 100% 的覆盖率,但受到以下事实的阻碍:有些代码行理论上是不可命中的(需要实现但从未被调用的方法, 的默认分支switch
语句等)。每个分支都包含一个 assert( false );
语句,但 gcov 仍然将它们标记为未命中。
我希望能够告诉 gcov 忽略这些分支。有没有办法给 gcov 提供这些信息——通过注释源代码,或者通过任何其他机制?
I'm using gcov to measure coverage in my C++ code. I'd like to get to 100% coverage, but am hampered by the fact that there are some lines of code that are theoretically un-hittable (methods that are required to be implemented but which are never called, default branches of switch
statements, etc.). Each of these branches contains an assert( false );
statement, but gcov still marks them as un-hit.
I'd like to be able to tell gcov to ignore these branches. Is there any way to give gcov that information -- by annotating the source code, or by any other mechanism?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请使用lcov。它隐藏了 gcov 的复杂性,产生良好的输出,允许每个测试的详细输出,具有简单的文件过滤和 - ta-taa - 已审查行的行标记:
来自 geninfo(1):
Please use lcov. It hides gcov's complexity, produces nice output, allows detailed output per test, features easy file filtering and - ta-taa - line markers for already reviewed lines:
From geninfo(1):
一个名为 gcovr 的工具可用于总结 gcov 的输出,并且(至少从 3.4 版开始)它支持与 lcov 相同的排除标记。
来自这个答案:
您还可以将上面的
'LCOV'
替换为'GCOV'
或'GCOVR'
。他们都工作。A tool called gcovr can be used to summarise the output of gcov, and (from at least version 3.4) it supports the same exclusion markers as lcov.
From this answer:
You can also replace
'LCOV'
above with'GCOV'
or'GCOVR'
. They all work.您能否介绍相关函数的单元测试,这些函数的存在只是为了通过直接攻击理论上无法命中的代码路径来关闭 gcov?由于它们是单元测试,因此它们可能会忽略这种情况的“不可能”。他们可以调用从未被调用的函数,传递无效的枚举值以捕获默认分支等。
然后,仅在使用 NDEBUG 编译的代码版本上运行这些测试,或者在测试断言是否正确的工具中运行它们触发 - 无论您的测试框架支持什么。
我觉得规范说代码必须在那里,而不是包含代码功能要求的规范有点奇怪。特别是,这意味着您的测试没有测试这些需求,这是保持需求功能的一个很好的理由。就我个人而言,我想修改规范,说“如果使用无效的枚举值调用,该函数将无法断言。调用者不得在发布模式下使用无效的枚举值调用该函数” 。或者一些这样的。
据推测,它目前所说的内容是“所有 switch 语句必须有一个默认情况”。但这意味着编码标准通过引入死代码来干扰可观察的行为(至少在 gcov 下可观察)。编码标准不应该这样做,因此功能规范应该尽可能考虑编码标准。
如果做不到这一点,您也许可以将不可命中的代码包装在
#if !GCOV_BUILD
中,并为 gcov 的利益进行单独的构建。此构建将无法满足某些要求,但只要您对代码的分析正确,它就会让您确信测试套件会测试其他所有内容。编辑:你说你正在使用一个狡猾的代码生成器,但你也通过注释源代码来寻求解决方案。如果您要更改源代码,在许多情况下您可以删除死代码吗?并不是说改变生成的源是理想的,但需要必须......
Could you introduce unit tests of the relevant functions, that exist solely to shut gcov up by directly attacking the theoretically-unhittable code paths? Since they're unit tests, they could perhaps ignore the "impossibility" of the situations. They could call the functions that are never called, pass invalid enum values to catch default branches, etc.
Then either run those tests only on the version of your code compiled with NDEBUG, or else run them in a harness which tests that the assert is triggered - whatever your test framework supports.
I find it a bit odd though for the spec to say that the code has to be there, rather than the spec containing functional requirements on the code. In particular, it means that your tests aren't testing those requirements, which is as good a reason as any to keep requirements functional. Personally I'd want to modify the spec to say, "if called with an invalid enum value, the function shall fail an
assert
. Callers shall not call the function with an invalid enum value in release mode". Or some such.Presumably what it currently says, is along the lines of "all switch statements must have a default case". But that means coding standards are interfering with observable behaviour (at least, observable under gcov) by introducing dead code. Coding standards shouldn't do that, so the functional spec should take account of the coding standards if possible.
Failing that, you could perhaps wrap the unhittable code in
#if !GCOV_BUILD
, and do a separate build for gcov's benefit. This build will fail some requirements, but conditional on your analysis of the code being correct, it gives you the confidence you want that the test suite tests everything else.Edit: you say you're using a dodgy code generator, but you're also asking for a solution by annotating the source code. If you're changing the source, can you just remove the dead code in many cases? Not that changing generated source is ideal, but needs must...
我不相信这是可能的。 Gcov 依赖 gcc 生成额外的代码来生成覆盖率输出。 GCov 本身只是解析数据。这意味着 Gcov 无法比 gcc 更好地分析代码(我假设您使用 -Wall 并删除了报告为无法访问的代码)。
请记住,可重定位函数可以从任何地方调用,甚至可能是外部 dll 或可执行文件,因此编译器无法知道哪些可重定位函数不会被调用或这些函数可能有什么输入。
您可能需要使用一些花哨的静态分析工具来获取您想要的信息。
I do not believe this is possible. Gcov depends on gcc to generate extra code to produce the coverage output. GCov itself just parses the data. This means that Gcov cannot analyze the code any better than gcc (and I assume you use -Wall and have removed code reported as unreachable).
Remember that relocatable functions can be called from anywhere, potentially even external dlls or executables so there is no way the compiler can know what relocatable functions will not be called or what input these functions may have.
You probably will need to use some facy static analysis tool to get the info that you want.