gcov lcov (一)
来源:互联网 发布:梦幻西游手游for mac 编辑:程序博客网 时间:2024/05/18 03:55
Gcov作为gnu/gcc工作组件之一,是一款的免费的代码覆盖率测试工具,而且可以结合lcov生成美观的html的测试报表。本文介绍一些gcov的使用方法,基本原理,一些实际中可能会遇到的问题以及解决思路。
- Gcov的用法
1.1 编译
Gcov的使用方法很简单,首先需要给gcc编译的时候打开覆盖测试的开关
例如要对srcfile.c单个文件生成的程序进行代码覆盖测试,在gcc编译的时候:
gcc -fprofile-arcs -ftest-coverage srcfile.c -o srcfile
或者简化成:
gcc --coverage srcfile.c -o srcfile
如果源文件很多,需要编译,链接的时候,在gcc编译的时候:
编译:
gcc -fprofile-arcs -ftest-coverage -c srcfile.c
链接:
gcc srcfile.o -o srcfile -lgcov
或者
gcc srcfile.o –o srcfile -fprofile-arcs
看出来了没有,gcov可以只针对大项目中的某几个单独的文件进行代码覆盖测试,只要在这几个文件编译的时候,加上-ftest-coverage,其他的文件不变就行了,爽吧。
1.2 生成报表
编译完成后会同时生成 *.gcno 文件(gcov notes),gcov生成覆盖率报告时需要参考该文件。
运行生成的可执行文件,给予正常的工作负载,待其正常退出后会生成覆盖率统计数据 *.gcda 文件(gcov data)
通过如下命令行之一查看覆盖率报告:
gcov 生成文本统计结果和带 line-count 标注的源代码:gcov srcfile
lcov 生成较正式的 HTML 报告:
lcov -c -d srcfile_dir -o srcfile.info
genhtml -o report_dir srcfile.info
注意:另外,编译选项中最好加入 -g3 -O0,前者是为了增加调试信息,后者是为了禁用优化,免得覆盖率测试不准确。
1.3 一个单文件的例子
一个例子程序如下:
#include <stdio.h>
#include <stdlib.h>
int
main(
int
argc,
char
* argv[]) {
int
i = 0;
printf
(
"Begin Test...n"
);
if
(1 == argc) {
printf
(
"argc == 1n"
);
}
else
{
printf
(
"argc != 1n"
);
for
(i = 0; i < argc; i++)
printf
(
"%dtoft%dn"
, i+1, argc);
}
printf
(
"End Test!n"
);
}
编译:
gcc
test
.c -fprofile-arcs -ftest-coverage -o
test
生成文件如下:
test
test
.c
test
.gcno
运行:
.
/test
1 2 3 4
生成文件如下:
test
test
.c
test
.gcda
test
.gcno
生成覆盖测试报告:
gcov
test
生成的test.gcov如下:
第一列是覆盖情况,第二列是行号加源程序,其中第一列中数字开头的是执行的次数,####开头的是没有执行到的语句。
2. Gcov的实现原理简介
Gcc中指定-ftest-coverage 等覆盖率测试选项后,gcc 会:
- 在输出目标文件中留出一段存储区保存统计数据
- 在源代码中每行可执行语句生成的代码之后附加一段更新覆盖率统计结果的代码
- 在最终可执行文件中进入用户代码 main 函数之前调用 gcov_init 内部函数初始化统计数据区,并将gcov_exit 内部函数注册为 exit handlers
- 用户代码调用 exit 正常结束时,gcov_exit 函数得到调用,其继续调用 __gcov_flush 函数输出统计数据到 *.gcda 文件中
2 对后台服务程序进行覆盖率测
从 gcc coverage test 实现原理可知,若用户进程并非调用 exit 正常退出,覆盖率统计数据就无法输出,也就无从生成报告了。后台服务程序若非专门设计,一旦启动就很少主动退出,用 kill 杀死进程强制退出时就不会调用 exit,因此没有覆盖率统计结果产生。
为了解决这个问题,我们可以给待测程序增加一个 signal handler,拦截 SIGHUP、SIGINT、SIGQUIT、SIGTERM 等常见强制退出信号,并在 signal handler 中主动调用 exit 或 __gcov_flush 函数输出统计结果即可。如何使用gcov完成对后台驻守程序的测试
该方案仍然需要修改待测程序代码,不过借用动态库预加载技术和 gcc 扩展的 constructor 属性,我们可以将 signalhandler 和其注册过程都封装到一个独立的动态库中,并在预加载动态库时实现信号拦截注册。这样,就可以简单地通过如下命令行来实现异常退出时的统计结果输出了:
LD_PRELOAD=.
/gcov_out
.so .
/daemon
测试完毕后可直接 kill 掉 daemon 进程,并获得正常的统计结果文件 *.gcda。
用来预加载的动态库gcov_out.so的代码如下,其中__attribute__ ((constructor))
是gcc的符号,它修饰的函数会在main函数执行之前调用,我们利用它把异常信号拦截到我们自己的函数中,然后调用__gcov_flush()输出错误信息
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#define SIMPLE_WAY
void
sighandler(
int
signo)
{
#ifdef SIMPLE_WAY
exit
(signo);
#else
extern
void
__gcov_flush();
// flush out gcov stats data
__gcov_flush();
// raise the signal again to crash process
raise
(signo);
#endif
}
__attribute__ ((constructor))
void
ctor()
{
int
sigs[] = {
SIGILL, SIGFPE, SIGABRT, SIGBUS,
SIGSEGV, SIGHUP, SIGINT, SIGQUIT,
SIGTERM
};
int
i;
struct
sigaction sa;
sa.sa_handler = sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESETHAND;
for
(i = 0; i <
sizeof
(sigs)/
sizeof
(sigs[0]); ++i) {
if
(sigaction(sigs[i], &sa, NULL) == -1) {
perror
(
"Could not set signal handler"
);
}
}
}
编译:
gcc -shared -fPIC gcov_out.c -o gcov_out.so
4. 参考资料
man gcc
man gcov
lcov – http://ltp.sourceforge.net/coverage/lcov.php
注意,lcov 最好使用 1.9 及以上版本,否则可能遇到如下错误:
geninfo: ERROR: …: reached unexpected end of file
转载:
http://blog.linezing.com/2011/03/%E4%BD%BF%E7%94%A8gcov%E5%AE%8C%E6%88%90%E4%BB%A3%E7%A0%81%E8%A6%86%E7%9B%96%E7%8E%87%E7%9A%84%E6%B5%8B%E8%AF%95
- gcov lcov (一)
- gcov、lcov与genhtml
- gcov、lcov与genhtml
- gcov,lcov常见问题
- gcov 和 lcov
- gcov和lcov
- gcov和lcov的使用
- gcov lcov覆盖率统计工具
- gcov和lcov使用经验
- 代码覆盖率测试,gcov, lcov
- Kcov - gcov, lcov and bcov
- 关于覆盖率GCOV(LCOV)
- gcov/lcov查看代码运行覆盖率
- gcov+lcov C代码覆盖率 初识
- gcov和lcov代码覆盖率工具
- gcov、lcov与genhtml 使用心得
- gcov、lcov与genhtml 使用心得
- gcov、lcov与genhtml 使用心得
- C#托管的 PInvoke 签名与非托管的目标签名匹配问题
- git如何使工程回到原来的版本
- 使用 Capistrano —— Rails应用快速部署工具
- opencv 学习第一天 学习opencv(中文版)创建一个类似滚动条
- 学生信息管理系统小结
- gcov lcov (一)
- El表达式
- Linux基本功一:文件相关命令初步
- 利用Qt对话框选择文件保存路径
- 深入了解MFC中的文挡/视结构
- JTAG、JLINK、ULINK、ST-LINK的区别
- Java乔晓松-android使用GridView布局的电子相册&服务器获取图片
- Git_Windows 系统下Git安装图解
- 一点近期装机组网的经验