编译链接实战(22)C/C++代码覆盖率统计报告生成

Gcov 查看代码覆盖率

文章目录

    • GCOV 工具简介
    • gcov 使用
    • lcov
    • 相关编译选项

GCOV 工具简介

gcov是一个测试代码覆盖率的工具,它是 gcc 自带的查看代码覆盖率的工具。

与GCC结合使用,可以分析您的程序以帮助创建更高效、运行更快的代码,并发现程序中未经测试的部分。您可以将gcov作为性能分析工具使用,以帮助发现优化工作对代码产生最佳效果的位置。您还可以将gcov与另一种性能分析工具gprof一起使用,以评估代码的哪些部分使用了最多的计算时间。

性能分析工具可以帮助您分析代码的性能。使用像gcov或gprof这样的分析器,您可以找出一些基本的性能统计数据,例如:

  • 每行代码执行了多少次
  • 实际执行了哪些代码行
  • 每个代码段使用了多少计算时间

一旦您了解了编译后的代码如何工作,就可以查看每个模块,看看哪些模块应该进行优化。gcov可以帮助您确定在哪里进行优化工作。

软件开发人员还结合测试套件使用覆盖率测试,以确保软件实际上足够好,可以发布。测试套件可以验证程序按预期工作;覆盖率程序测试测试套件执行了程序的多少部分。然后,开发人员可以确定需要向测试套件中添加哪些类型的测试用例,以创建更好的测试和更好的最终产品。

如果您计划使用gcov,应该在不优化的情况下编译代码,因为通过将一些代码行组合成一个函数的优化,可能无法为您提供寻找“热点”所需的信息,即代码使用大量计算时间的地方。同样,因为gcov按行(最低分辨率)累积统计数据,它最适合一种编程风格,即每行只放置一个语句。如果您使用复杂的宏,这些宏展开为循环或其他控制结构,统计数据就不那么有用——它们只报告宏调用出现的行。如果您的复杂宏表现得像函数,您可以用内联函数替换它们来解决这个问题。

gcov创建一个名为sourcefile.gcov的日志文件,指示源文件sourcefile.c的每一行执行了多少次。您可以将这些日志文件与gprof一起使用,以帮助微调程序的性能。gprof提供您可以与从gcov获得的信息一起使用的计时信息。

gcov仅适用于用GCC编译的代码。它与任何其他性能分析或测试覆盖机制不兼容。

使用效果如下图所示:

img

程序运行完成后,可以查看每个文件的代码覆盖率情况,上面报告中展示了每个文件的行覆盖率,函数覆盖率和分支覆盖率。

打开一个文件的覆盖率报告,页面对开始有文件的基本信息描述,以 FreeRTOS 的 task.c 为例,它的有效代码行数为 921 行,共 24 个函数(几千行的文件其实也没多少嘛~)

img

img

在覆盖率的正文,有该文件的完整代码,并用不同颜色进行高亮标注了:

  • 蓝色表示运行被覆盖的代码,前面的数字表示代码执行次数。
  • 红色表示未执行代码。
  • 白色表示无效代码,包括注释,空行和未编译代码。

gcov 使用

使用 gcov 的流程非常简单,只需要三步即可。 下面以 hello world 为例,展示生成覆盖率报告。

代码如下:

//main.c#include <stdio.h>int main(int argc, char **argv) {printf("hello world\n");return 0;
}

第一步: 添加编译参数 -fprofile-arcs -ftest-coverage

在所需要的生产覆盖率的文件中,添加编译参数,编译代码生成目标文件,同时会生成 *.gcno 文件,其中包含文件的行号等信息。
GCC C/C++代码覆盖率统计生成

gcc main.c -c -fprofile-arcs -ftest-coverage -o main.o
ls # 输出文件列表:
# main.c  main.gcno  main.o
gcc main.o -lgcov -o main

第二步: 添加链接参数 -lgcov ,运行程序

运行程序后,会生成一个 *.gcda 文件,里面包含代码执行次数等数据。

gcc main.o -lgcov -o main
# 运行程序
./main
# hello world
ls # 输出文件列表:
#main  main.c  main.gcda  main.gcno  main.o

第三步: 输出覆盖率报告 使用下面命令输出覆盖率报告

# 第一次使用前安装工具
sudo apt install lcov# 生成覆盖率文本报告
lcov -c -d . -o test.info --rc lcov_branch_coverage=1 
# 生成覆盖率网页报告
genhtml --branch-coverage -o result test.info 

输入上面两/三条命令后在,执行命令的文件路径可以看到一个 result 文件夹,在里面就是对应的网页覆盖率报告。

img

用浏览器打开 index.html 就可以看到最开始展示的覆盖率信息了。

lcov

lcov 是 GCC 覆盖率测试工具 gcov 的图形化前端,用于收集多个源文件的行、函数和分支覆盖率数据,并创建包含覆盖信息的 HTML 页面。它还添加了概览页面,以便在文件结构中进行方便的导航。

使用 lcov 收集覆盖率数据,并使用 genhtml 创建 HTML 页面。覆盖率数据可以从当前正在运行的 Linux 内核或用户空间应用程序中收集。要做到这一点,您需要完成以下准备步骤:

  1. 收集覆盖率数据:首先,使用 lcov 工具来收集代码的覆盖率数据。您可以通过在编译时添加 -ftest-coverage-fprofile-arcs 选项来生成覆盖率数据的中间文件。然后,通过运行应用程序或测试套件来执行代码路径,以便生成覆盖率数据。
  2. 生成 HTML 页面:接下来,使用 genhtml 工具将收集到的覆盖率数据转换为 HTML 页面。genhtml 将分析覆盖率数据,并生成带有覆盖信息注释的源代码的 HTML 页面,以及用于导航文件结构的概览页面。

这些工具的结合使用使得开发人员能够更直观地查看代码的覆盖情况,从而更好地理解测试覆盖范围和质量。通过分析生成的 HTML 页面,开发人员可以识别哪些部分的代码需要更多的测试覆盖,以及哪些部分已经得到了良好的覆盖。

总的来说,lcov 和 genhtml 工具的组合为开发人员提供了一种强大的方式来收集和可视化代码覆盖率数据,从而帮助他们更好地进行测试和代码质量管理。如果您需要进一步解释或有其他问题,请随时告诉我,我很乐意为您提供帮助。

关键选项:

   -r tracefile pattern--remove tracefile patternRemove data from tracefile.Use this switch if you want to remove coverage data for a particular set of files from a tracefile. Additional command line parameters will be interpreted as  shell  wildcard  patterns  (notethat they may need to be escaped accordingly to prevent the shell from expanding them first).  Every file entry in tracefile which matches at least one of those patterns will be removed.Note: The pattern must be specified to match the absolute path of each source file.The result of the remove operation will be written to stdout or the tracefile specified with -o.Only one of  -z, -c, -a, -e, -r, -l, --diff or --summary may be specified at a time.--exclude patternExclude source files matching pattern.Use this switch if you want to exclude coverage data for a particular set of source files matching any of the given patterns. Multiple patterns can be specified by  using  multiple  --excludecommand line switches. The patterns will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first).Note: The pattern must be specified to match the absolute path of each source file.Can be combined with the --include command line switch. If a given file matches both the include pattern and the exclude pattern, the exclude pattern will take precedence.
 --include patternInclude source files matching pattern.Use this switch if you want to include coverage data for only a particular set of source files matching any of the given patterns. Multiple patterns can be specified by using  multiple  --in‐clude command line switches. The patterns will be interpreted as shell wildcard patterns (note that they may need to be escaped accordingly to prevent the shell from expanding them first).Note: The pattern must be specified to match the absolute path of each source file.
       --rc keyword=valueOverride a configuration directive.Use  this option to specify a keyword=value statement which overrides the corresponding configuration statement in the lcovrc configuration file. You can specify this option more than once tooverride multiple configuration statements.  See lcovrc(5) for a list of available keywords and their meaning.

相关编译选项

  • -fprofile-arcs

该选项用于在程序执行时对程序流程弧进行插装,记录每个分支和调用被执行的次数以及它们被取或返回的次数。对于支持具有优先级支持的构造函数的目标,剖析能够正确处理构造函数、析构函数以及用作全局变量类型的类的C++构造函数(和析构函数)。

当编译后的程序退出时,会将这些数据保存到名为 auxname.gcda 的文件中,每个源文件都会生成一个相应的 .gcda 文件。这些数据可以用于基于profile-directed 的优化(例如 -fbranch-probabilities),或者用于测试覆盖率分析(例如 -ftest-coverage)。每个目标文件的 auxname 是从输出文件的名称生成的,如果显式指定了输出文件并且它不是最终可执行文件,则 auxname 会采用源文件的基本名称。在这两种情况下,任何后缀都会被移除(例如对于输入文件 dir/foo.cauxnamefoo.gcda;对于指定为 -o dir/foo.o 的输出文件,auxnamedir/foo.gcda)。

简而言之,通过使用 -fprofile-arcs 编译选项,您可以收集程序在执行过程中的代码覆盖率和执行路径信息,从而可以进行优化或测试覆盖率分析。

  • –coverage

这个选项是 -fprofile-arcs -ftest-coverage(编译时)和 -lgcov(链接时)的同义词。主要做了以下工作:

  1. 使用 -fprofile-arcs 和优化、代码生成选项来编译源文件。对于测试覆盖率分析,还需额外加上 -ftest-coverage 选项。并不需要对程序中的每个源文件都进行剖析。
  2. 另外使用 -fprofile-abs-path 选项来编译源文件,以在 .gcno 文件中创建绝对路径名。这样可以让 gcov 在项目中的编译发生在不同工作目录的情况下正确找到源文件。
  3. 使用 -lgcov-fprofile-arcs(后者暗含了前者)来链接您的目标文件。
  4. 运行程序以生成弧剖析信息。可以多次重复这个过程。您可以同时运行多个程序实例,只要文件系统支持锁定,数据文件就会被正确地更新。除非启用了严格的 ISO C 方言选项,否则 “fork” 调用会被检测并正确处理,而不会重复计数。
  5. 对于基于profile-directed的优化,需要使用相同的优化和代码生成选项再次编译源文件,并加上 -fbranch-probabilities
  6. 对于测试覆盖率分析,使用 gcov 从 .gcno.gcda 文件中生成人类可读的信息。请参考 gcov 文档以获取更多信息。
    特殊环境使用注意点:

在正常使用 gcov 是非常简单的,但是在特殊项目中使用 gcov 需要注意一些坑,否则就会跟我一样掉进去出不来。。。

  • 链接时,会在 .init_array 段插入 __gcov_init() 函数,该函数在 main 运行之前初始化 gcov 运行环境。
  • 如果修改过链接脚本,注意 .init_array 的全局构造函数是否执行成功。
  • 和上面一样,链接时,会在全局析构函数中插入 __gcov_exit() 函数,在 main 执行结束后,输出 *.gcda 文件。
  • 如果程序为异常退出,则不会生成 *.gcda 文件,此时需要在代码适当位置插入 __gcov_flush() 函数,将文件进行保存。
  • 默认状态 *.gcda 文件和 *.gcno 文件所在文件夹相同,如果需要修改输出文件夹,可通过添加环境变量:GCOV_PREFIX 和 GCOV_PREFIX_STRIP
  • GCOV_PREFIX_STRIP=16 , 为将原有路径裁剪16个文件夹。 GCOV_PREFIX=/home/tester/build , 为将裁剪后的路径添加前缀 例如:上文中默认 main.gcda 所在的文件 /home/tester/main.gcda,裁剪后添加前缀后变为/home/tester/build/main.gcda

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PCIE 4.0 L0s/L1/L2

L0是PCIE设备正常工作的状态&#xff0c;当设备链路处于非工作状态可以跳转大相应的低功耗状态&#xff0c;L0s是一种可以快速恢复到L0的低功耗状态&#xff1b;L1必须经过Reovery状态才可以恢复到L0状态&#xff1b;L2需要从Detect开始逐步进入到L0状态。它们的恢复时间依次延…

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统)

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统) 部署ffmpeg用来处理视频的各种操作 想使用ffmpeg&#xff0c;要先安装nasm&#xff0c;yasm&#xff0c;x264之后&#xff0c;否则会报错 nkvers 查看麒麟操作系统版本 cat /proc/version #查看linux版本信息 uname -a …

Android修行手册-Chaquopy中opencv、numpy的初步应用

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

SpringBoot源码解读与原理分析(三十八)SpringBoot整合WebFlux(一)WebFlux的自动装配

文章目录 前言第13章 SpringBoot整合WebFlux13.1 响应式编程与Reactor13.1.1 命令式与响应式13.1.2 异步非阻塞13.1.3 观察者模式13.1.4 响应性13.1.5 响应式流13.1.6 背压13.1.7 Reactor13.1.7.1 Publisher13.1.7.2 Subscriber13.1.7.3 Subscription13.1.7.4 Processor13.1.7.…

Leetcoder Day32| 贪心算法part05

763.划分字母区间 字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。 示例&#xff1a; 输入&#xff1a;S "ababcbacadefegdehijhklij"输出&#xff1a;[9,7…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 3月2日,星期六

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年3月2日 星期六 农历正月廿二 1、 气象局&#xff1a;3月份仍有5次冷空气影响我国&#xff1b;全国多地或提前入春。 2、 央行&#xff1a;将外籍来华人员移动支付单笔交易限额由1000美元提高到5000美元。 3、 神舟十七号航…

【源码】imx6ull实现触摸屏单点实验

一、本实验实验的器材&#xff1a; 1.正点原子imx6ull的阿尔法开发板v2.2 2.屏幕ALIENTEK 4.3 RGBLCD 二、实验已经移植好的文件&#xff1a; 仓库代码&#xff1a;https://gitee.com/wangyoujie11/atkboard_-linux_-driver.git 1.文件说明 23_multitouch &#xff1a;驱动代…

【YOLO v5 v7 v8 小目标改进】ODConv:在卷积核所有维度(数量、空间、输入、输出)上应用注意力机制来优化传统动态卷积

ODConv&#xff1a;在卷积核所有维度&#xff08;数量、空间、输入、输出&#xff09;上应用注意力机制来优化传统的动态卷积 提出背景传统动态卷积全维动态卷积效果 小目标涨点YOLO v5 魔改YOLO v7 魔改YOLO v8 魔改 论文&#xff1a;https://openreview.net/pdf?idDmpCfq6Mg…

leedcode刷题--day7(字符串)

23 文章讲解 力扣地址 C class Solution { public:void reverseString(vector<char>& s) {int left 0;int right s.size() - 1; // right 应该初始化为 s.size() - 1while (left < right) {swap(s[left], s[right]); // 直接交换 s[left] 和 s[right] 的值lef…

(学习日记)2024.02.29:UCOSIII第二节

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

WSL2外部网络设置

1 关闭所有WSL系统 wsl --shutdown 2 打开Hyper-V管理器 3 将“虚拟交换机管理器”-> ”WSL连接类型“设置为“外部网络” 4 启动WSL系统&#xff0c;手动修改WSL网络 将WSL网络IP修改为192.168.1.9 sudo ip addr del $(ip addr show eth0 | grep inet\b | awk {print $2} |…

FinalMLP:用于推荐系统的简单但强大的双流 MLP 模型

原文地址&#xff1a;FinalMLP: A Simple yet Powerful Two-Stream MLP Model for Recommendation Systems 了解 FinalMLP 如何转变在线推荐&#xff1a;通过尖端 AI 研究解锁个性化体验 2024 年 2 月 14 日 介绍 世界正在向数字时代发展&#xff0c;在这个时代&#xff0c;…

持安科技孙维伯:零信任在攻防演练下的最佳实践|DISCConf 2023

近日&#xff0c;在2023数字身份安全技术大会上&#xff0c;持安科技联合创始人孙维伯应主办方的特别邀请&#xff0c;发表了主题为“零信任在攻防演练下的最佳实践”的演讲。 孙维伯在2023数字身份安全技术大会上发表演讲 以下为本次演讲实录&#xff1a; 我是持安科技的联合…

【c++】 STL的组件简介与容器的使用时机

STL六大组件简介 STL提供了六大组件&#xff0c;彼此之间可以组合套用&#xff0c;这六大组件分别是:容器、算法、迭代器、仿函数、适配器&#xff08;配接器&#xff09;、空间配置器。 容器&#xff1a;各种数据结构&#xff0c;如vector、list、deque、set、map等,用来存放…

微信云开发-- Mac安装 wx-server-sdk依赖

第一次上传部署云函数时&#xff0c;会提示安装依赖wx-server-sdk 一. 判断是否安装wx-server-sdk依赖 先创建一个云函数&#xff0c;然后检查云函数目录。 如果云函数目录下只显示如下图所示三个文件&#xff0c;说明未安装依赖。 如果云函数目录下显示如下图所示四个文件&a…

EdgeX Foundry 边缘物联网中间件平台

文章目录 1.EdgeX Foundry2.平台架构3.平台服务3.1.设备服务3.2.核心服务3.3.支持服务3.4.应用服务3.5.安全服务3.6.管理服务 EdgeX Foundry # EdgeX Foundryhttps://iothub.org.cn/docs/edgex/ https://iothub.org.cn/docs/edgex/edgex-foundry/1.EdgeX Foundry EdgeX Found…

嵌入式 Linux 下的 LVGL 移植

目录 准备创建工程修改配置修改 lv_drv_conf.h修改 lv_conf.h修改 main.c修改 Makefile 编译运行更多内容 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个轻量化的、开源的、在嵌入式系统中广泛使用的图形库&#xff0c;它提供了一套丰富的控件和组件…

微软为金融界带来革命性突破——推出Microsoft 365中的下一代AI助手:Microsoft Copilot for Finance

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

雷龙CS SD NAND(贴片式TF卡)测评体验

前段时间有幸免费得到了雷龙出品的贴片式的TF卡的芯片及转接板&#xff0c;两片贴片式nand芯片&#xff0b;一个转接板&#xff0c;一种一个已让官方焊接完好&#xff1b;如下图所示&#xff1a; 正面&#xff1a; 背面&#xff1a; 通过转接板&#xff0c;可以将CS SD NAND(贴…

数电实验之流水灯、序列发生器

最近又用到了数电实验设计的一些操作和设计思想&#xff0c;遂整理之。 广告流水灯 实验内容 用触发器、组合函数器件和门电路设计一个广告流水灯&#xff0c;该流水灯由 8 个 LED 组成&#xff0c;工作时始终为 1 暗 7 亮&#xff0c;且这一个暗灯循环右移。 1) 写出设计过…