必须同时加 -fprofile-arcs 和 -ftest-coverage,否则 gcov 无法采集覆盖率数据;前者在分支插入计数代码,后者生成 .gcno 结构信息文件,二者缺一不可,且需配合 -o0 -g、正确路径权限、lcov --capture 及 genhtml 完整流程才能生成有效报告。

必须同时加 -fprofile-arcs 和 -ftest-coverage,否则 gcov 看不到任何覆盖率数据——它不自动采集,全靠编译器插桩埋点。
编译时漏掉任一 flag 就白忙
常见错误现象:gcov 报告全是 #####(表示无计数),或 lcov 生成的 HTML 里所有行标灰、覆盖率为 0。
-
-fprofile-arcs:在分支跳转处插入计数代码 -
-ftest-coverage:生成.gcno文件(含源码结构信息),供后续解析 - 两者缺一不可,且仅对
gcc/g++编译的目标文件生效 - CMake 项目需显式追加到
target_compile_options或CMAKE_CXX_FLAGS,不能只写在链接阶段 - 建议关闭优化(
-O0)并保留调试符号(-g),否则行号映射错乱、覆盖率归位不准
运行测试后 .gcda 不自动生成?检查路径和权限
.gcda 是运行时生成的计数文件,不是编译产物。它默认写入可执行文件所在目录,但常因工作目录、权限或环境变量导致失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 确保测试程序有写权限:比如
./build/test运行后,build/下应出现test.gcda - 若二进制和源码不在同一目录,用
GCOV_PREFIX指定.gcda输出根路径,避免被写到临时位置 - 别手动删
.gcda:每次测试后它记录的是增量计数,lcov --capture需要合并多个.gcda,删了就丢数据 - 多进程/多线程测试要注意:默认
gcov计数非原子,加-fprofile-update=atomic更稳妥(尤其lcov 2.0+)
lcov --capture 才是真正起点,不是直接喂 .gcda
lcov 不直接读 .gcda,必须先用 --capture 扫描并解析所有匹配的 .gcda+.gcno 对,生成中间格式 .info。
- 典型命令:
lcov --capture --directory build/ --output-file coverage.info - 若
.gcno路径与当前工作目录不一致(如 CMake 构建在build/,但源码在src/),lcov会静默跳过该文件——检查lcov输出末尾是否有 “skipped” 提示 - 过滤第三方头文件必须用
-r(不是--exclude):lcov -r coverage.info '/usr/*' '*/gtest/*' '*/fmt/*' --output-file coverage.filtered.info;通配符务必用单引号包裹,防 shell 展开 - 路径通配要覆盖 header-only 库(如
spdlog、range-v3),否则它们的头文件会被计入分母,拉低整体覆盖率
生成 HTML 后打不开?别双击 index.html
genhtml 输出的 HTML 依赖内联 JS 实现搜索、折叠等功能,Chrome/Firefox 直接打开 file:// 协议会禁用脚本,页面空白或只剩骨架。
- 正确做法:起一个本地 HTTP 服务,例如
python3 -m http.server 8000,然后访问http://localhost:8000/coverage_report/ - 若报告中函数名或文件路径显示为绝对路径(如
/home/user/project/src/foo.cpp),可在genhtml加--prefix重写:genhtml --prefix "/home/user/project" coverage.filtered.info --output-directory coverage_report - 大工程首次生成可能卡顿几秒——
genhtml要遍历所有源文件并渲染高亮,耐心等完再刷新,别中途关掉
最容易被忽略的一点:.gcno 和 .gcda 必须来自同一轮编译+运行;混用不同构建产物会导致 lcov 解析失败或覆盖率归零,且错误不报——它只是跳过,连 warning 都没有。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










