C ++ code coverage profiling with GCC/gcov
Submitted by bobah on Wed, 01/27/2010-17:42
Http://www.bobah.net/d4d/tools/code-coverage-with-gcov
The coverage analysis with GCC/gcov includes three following steps
* Instrumented application build-libraries, executable (s), and profiling artifacts (*. gcno files) are created
* The application test run (s)-the runtime coverage statistics (*. gcda files) is collected
* Coverage statistics post-processing with gcov/lcov-text/html coverage reports are generated
Instrumented application build
To enable the instruments Compilation Use gcc/g ++ with -- coveragee flag. the Know-How here is to specify the full path to source files during the compilation in order to be able to perform a cross-profiling and adjust the use of lcov (described below ).
$ G ++-C-g-O0 -- Coverage-o $ PWD/obj/myclass. o $ PWD/myclass. cpp
$ G ++-C-g-O0 -- Coverage-o $ PWD/obj/Main. o $ PWD/Main. cpp
$ G ++-g-O0 -- Coverage-o $ PWD/bin/MyApp $ PWD/obj/*. o
The GNU make has two useful functions to convert filenames to absolute ones: $ (abspath...) and $ (relpath ...)
When compiling with -- Coverage flag, *. gcno file is created in the same location, as the object file. this file is used by gcov for post-processing application's statistics collected at runtime and contains profiling arcs information.
$ Ls $ PWD/obj
Main. gcno main. O myclass. gcno myclass. o
$
Coverage statistics collection
An instrumented application collects coverage statistics at runtime and creates a set *. gcda files (or updates existing ones) on exit. for every *. gcno file created during the build a corresponding *. gcda file is created by the instrumented application upon exit. for *. gcda files to be generated, the application must exit cleanly by either returning from main () or by calling exit ().
For client/server applications I typically install sigterm handler to ensure a clean application termination.
The directory, where *. gcda files are to be created shocould exist and be writable by the application. A *. gcda file is created by default in the directory where the corresponding *. gcno file was created during the build.
To find out the exact location the following command can be used
$ Strings $ PWD/bin/MyApp | egrep '. gcda $'
/Home/bobah/work/coverage/obj/Main. gcda
/Home/bobah/work/coverage/obj/myclass. gcda
In response cases the coverage statistics shocould be collected from the application running on the environment (host, user etc .) other then the one where the application was built, so creating *. gcda files in the build directory may be impossible or impractical. to override the location to store *. gcda files two environment variables can be used: gcov_prefix and gcov_prefix_strip. for example, if we want to replace the four leading elements in the path ("/home/bobah/work/coverage") Where MyApp stores *. gcda with "/home/bobah/work/cov_rpt" We wocould need to define the variables as follows (Bash syntax) in the application's Environment
Export gcov_prefix = "/home/bobah/work/cov_rpt"
Export gcov_prefix_strip = 4
As a result of the override, the file myclass. gcda will be created in/home/bobah/work/cov_rpt and not in/home/bobah/work/coverage
Note, that for the post processing of the coverage data the most convenient way is to release source files and *. gcno artifacts to under $ gcov_prefix, so that *. gcda file is created in the same directory as corresponding *. gcno
I do it using rsync like
Rsync-ACV -- filter = '+ */' -- filter = '+ *. CPP '-- filter =' + *. h' -- filter = '+ *. gcno' -- filter = '-*'/home/bobah/work/coverage // home/bobah/work/cov_rpt
The coverage data is accumulated during subsequent application runs. to reset the counters either delete all *. gcda files under $ gcov_prefix directory
$ Find $ gcov_prefix-type F-name '*. gcda'-print | xargs/bin/Rm-F
Or use lcov functionality
$ Lcov -- directory $ gcov_prefix -- zerocounters
Post-processing runtime coverage statistics
I prefer using lcov wrapper for the coverage data processing because it generates nicely looking HTML reports.
The essential bit here is that the source code tree is available in exactly the same place as it was during the build. this is required because gcov application behavior can't be manipulated using gcov_prefix/gcov_prefix_strip and it expects files exactly as they are stored in *. gcno files.
The data post processing:
$ Lcov -- directory $ gcov_prefix -- capture -- output-File $ gcov_prefix/app.info
The HTML reports generation:
$ Genhtml -- output-directory $ PWD/cov_htmp $ gcov_prefix/app.info
Troubleshooting
"Stamp mismatch with graph file" error message during gcov/lcov Invocation
The *. gcno file contains a time stamp tag. the same tag is put to the runtime coverage report *. gcda file by the application. if the application and *. gcda files are created in the different build runs, gcov will refuse processing them.
The tag can be extracted from a file and compared *. gcda vs *. gcno
$ Hexdump-e '"% x/N"'-S8-N4 myclass. gcda
7ef26ee7
$ Hexdump-e '"% x/N"'-S8-N4 myclass. gcno
7ef26ee7
*. Gcda files are not generated
Here there can be 2 possibilities, either the directory where the applkication wants to write *. gcda file does not exist or is not writable, or the application does not exit property by either returning from main () or calling exit (), typically when sigterm is not properly handled