必须用-g -O0 --coverage编译,否则lcov无法获取有效.gcda数据,报告将显示“no data”或空白;-g确保源码行号可见,-O0防止优化干扰统计,--coverage生成.gcno和.gcda文件;运行测试后在.o所在目录执行lcov --capture,再用-r过滤系统及第三方路径,最后用genhtml生成报告并以本地HTTP服务打开。

必须用 -g -O0 --coverage 编译,否则 lcov 拿不到有效 .gcda 数据,生成的报告全是 “no data” 或空白。
编译阶段:三个标志一个都不能少
缺 -g → 没源码行号,genhtml 显示不了哪一行被覆盖;开优化(比如 -O2)→ 函数内联、死代码消除,.gcda 统计错位甚至崩溃;不加 --coverage → 根本不生成 .gcda 和 .gcno。
g++ -g -O0 --coverage -std=c++17 test.cpp -o test- CMake 用户需同时在
CMAKE_CXX_FLAGS和CMAKE_EXE_LINKER_FLAGS中添加--coverage - 若用
lcov 2.0+,建议额外加-fprofile-update=atomic避免警告
运行与捕获:.gcda 不在源码目录,而在 .o 所在路径
没运行测试程序,就不会生成 .gcda;运行了但工作目录不对,.gcda 就写到别处去了。CMake out-of-source 构建时,.gcda 默认落在 build/CMakeFiles/xxx.dir/ 下,不是 src/ 或可执行文件所在目录。
- 先确保
./test正常退出(非 crash / kill) - 在构建目录(即
.o和.gcda所在目录)执行:lcov -d . -c -o coverage_base.info - 不要在源码根目录或安装目录下执行
lcov --capture,否则扫不到.gcda
过滤路径:用 -r 排除系统头文件和第三方代码
默认 lcov 会把所有扫描到的 .gcda 对应源码都计入,包括 /usr/include/c++、catch2.hpp、fmt/format.h,导致覆盖率虚高、报告臃肿、加载卡顿。
立即学习“前端免费学习笔记(深入)”;
- 过滤命令必须后于
--capture:lcov -r coverage_base.info '/usr/*' '*/test/*' '*/third_party/*' '*/include/*' -o coverage_filtered.info - 路径是 shell glob,不是正则;
'*/include/*'能匹配build/_deps/fmt-src/include/,但'/include/*'无效 - header-only 库(如
spdlog、range-v3)的头文件路径也得加进-r列表
生成 HTML 报告:别直接双击打开 index.html
genhtml 输出的是纯静态文件,但现代浏览器(Chrome/Firefox)对 file:// 协议有限制,会禁用内联 JS(搜索框、折叠逻辑),导致页面白屏或只显示骨架。
- 正确做法:
genhtml coverage_filtered.info -o coverage_report,然后用本地 HTTP 服务打开:python3 -m http.server 8000,再访问http://localhost:8000/coverage_report/index.html - 输出目录不能和源码同名(如叫
src),否则可能覆盖源文件;也不建议放在build/下,容易被make clean清掉 - 如果报告里函数名显示为
???,大概率是编译时漏了-g,或.gcda和.gcno版本不匹配(比如 GCC 升级后没重编)
最易忽略的一点:lcov --capture 只抓当前目录下已存在的 .gcda,不会等待你后续运行测试;很多人跑完 lcov 才去执行程序,结果数据为空。顺序只能是 —— 编译 → 运行 → 再捕获。



















