Measuring Code Coverage for C/C++ Projects with Gcov and LCOV
This article explains how to measure code coverage for C/C++ projects using GCC's built‑in Gcov tool and the LCOV utility, covering prerequisite setup, compilation with profiling flags, running tests, generating .gcno/.gcda files, producing .gcov reports, creating HTML visualizations, and cautions against over‑relying on coverage percentages.
This article demonstrates how to use Gcov and LCOV to measure code coverage for C/C++ projects, providing a practical guide from environment setup to report generation and discussing the limitations of coverage metrics.
Problem
Many legacy C/C++ projects lack unit tests and rely on regression testing, making it difficult to know which code paths are exercised and where test coverage can be improved.
Current Situation
Commercial tools such as Squish Coco and Bullseye insert instrumentation during compilation to record execution, but they can be costly and introduce build complications. GCC already includes a built‑in coverage tool called Gcov .
Prerequisites
To follow the tutorial you need GCC and LCOV installed. The example source code is available at https://github.com/shenxianpeng/gcov-example . The repository’s master branch contains the source, while the coverage branch’s out directory holds the generated reports.
# 这是我的测试环境上的 GCC 和 lcov 的版本
sh-4.2$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
sh-4.2$ lcov -v
lcov: LCOV version 1.14How Gcov Works
The workflow consists of three main steps:
Compile with special flags ( -fprofile-arcs and -ftest-coverage ) to generate .gcno files.
Run the resulting executable to produce .gcda data files.
Use gcov to convert .gcno and .gcda into .gcov reports, then feed them to LCOV for HTML visualization.
1. Compilation
The required compile options are defined in the makefile . Running make builds the program and creates the profiling files.
make sh-4.2$ make
gcc -fPIC -fprofile-arcs -ftest-coverage -c -Wall -Werror main.c
gcc -fPIC -fprofile-arcs -ftest-coverage -c -Wall -Werror foo.c
gcc -fPIC -fprofile-arcs -ftest-coverage -o main main.o foo.oThe compilation produces .gcno files alongside the object files.
2. Running the Executable
Execute the program to generate .gcda files.
./main sh-4.2$ ./main
Start calling foo() ...
when num is equal to 1...
when num is equal to 2...Each source file now has a corresponding .gcda file containing execution counts.
3. Generating the Report
Run make report to invoke gcov and then LCOV.
make report sh-4.2$ make report
gcov main.c foo.c
File 'main.c'
Lines executed:100.00% of 5
Creating 'main.c.gcov'
File 'foo.c'
Lines executed:85.71% of 7
Creating 'foo.c.gcov'
Lines executed:91.67% of 12
lcov --capture --directory . --output-file coverage.info
... (output omitted for brevity) ...
Overall coverage rate:
lines......: 91.7% (11 of 12 lines)
functions..: 100.0% (2 of 2 functions)The command performs two actions: (1) runs gcov on the source files to produce .gcov files, and (2) uses LCOV to aggregate the data and generate an HTML report.
# 1. Generate coverage.info data file
lcov --capture --directory . --output-file coverage.info
# 2. Generate HTML report
genhtml coverage.info --output-directory outCleaning Up
All generated files can be removed with make clean :
sh-4.2$ make clean
rm -rf main *.o *.so *.gcno *.gcda *.gcov coverage.info outCode Coverage Report
The HTML report shows covered lines in blue and uncovered lines in red, supporting line, function, and branch coverage.
Don’t Overestimate Coverage Metrics
High coverage percentages do not guarantee effective testing; they only indicate which code was executed. Striving for 100% coverage can lead to meaningless tests that add little value. As Martin Fowler notes, coverage is useful for locating untested code but is a poor indicator of test quality.
Further Reading
Using Gcov in the Linux kernel – example
Setting environment variables for cross‑profiling – documentation
References
Squish Coco – https://shenxianpeng.github.io/2019/05/squishcoco/
Gcov – https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
GCC – https://gcc.gnu.org/install/index.html
LCOV – http://ltp.sourceforge.net/coverage/lcov.php
gcovr – https://github.com/gcovr/gcovr
Martin Fowler on Test Coverage – https://www.martinfowler.com/bliki/TestCoverage.html
DevOps Engineer
DevOps engineer, Pythonista and FOSS contributor. Created cpp-linter, commit-check, etc.; contributed to PyPA.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.