PAYATHON 2026

GCC 14.2.0 静态程序为何只生成部分 .gcda 文件?

数据小陈

结论

现有信息不足以确认这是 GCC 14.2.0 的 libgcov 回归。.gcda 文件数量少时,可以先检查哪些插桩目标文件实际进入了最终可执行文件、GCOV_PREFIX 把输出重定向到了哪里,以及程序是否正常退出并写出数据。

GCC 文档说明,使用 -ftest-coverage 编译时会生成 .gcno;程序执行时,编入了 -fprofile-arcs 插桩的目标文件会生成对应的 .gcda。--coverage 包含编译所需的两个覆盖率选项,并会在链接时启用 -lgcov。GCC 14.2 Instrumentation Options Gcov Data Files

先确认文件实际写到了哪里

GCOV_PREFIX 和 GCOV_PREFIX_STRIP 是运行时路径重定位设置,不是构建时开关。要让目标程序使用这两个变量,需要在启动程序的环境中设置。GCC 会先从编译时记录的对象文件路径中去掉指定数量的目录,再加上 GCOV_PREFIX。因此,GCOV_PREFIX_STRIP=3 是否合适,要看构建机上的对象文件实际路径。GCC 14.2 Cross-profiling

ls /tmp/gcov_test/*/obj.*/ 只会检查特定层级,无法排除其他层级存在 .gcda。可以在目标机上递归查找:

GCOV_PREFIX=/tmp/gcov_test \
GCOV_PREFIX_STRIP=3 \
./test_gcc14

find /tmp/gcov_test -type f -name '*.gcda' -print
find /tmp/gcov_test -type d -print

将找到的 .gcda 与构建产物中的 .gcno 对照。如果文件出现在意料之外的路径,检查对象文件编译时记录的绝对路径,并相应调整 GCOV_PREFIX_STRIP。同时确认运行程序的用户对 /tmp/gcov_test 有写入权限。

检查实际参与链接的目标文件

.gcno 存在,只能说明相应源文件曾经编译过,不能证明对应的目标文件最终进入了正在运行的可执行文件。例如,静态库中未被链接器提取的成员不会因为存在 .gcno 就自动生成运行数据;链接时被裁剪的代码也可能不在最终程序中。

先从构建日志确认每个相关源文件都使用了覆盖率插桩,再检查链接输入和实际二进制。如果项目使用静态库、--gc-sections、LTO 或优化,留意这些设置是否导致部分目标文件或函数未进入最终程序。逐个核对 .gcno 和 .gcda 的配对情况,可以判断问题更可能出在目标文件未编入程序,还是运行时没有写出数据。

简化覆盖率构建参数

最小示例可以用 --coverage 同时指定编译和链接选项:

gcc-14.2.0 -m32 --coverage -static test.c -o test_gcc14

如果项目分开编译和链接,编译阶段和链接阶段都使用 --coverage,并确认选项传给了正确的编译器驱动。GCC 文档将 --coverage 定义为编译时 -fprofile-arcs -ftest-coverage 和链接时 -lgcov 的同义选项。只在最终链接命令中添加覆盖率选项是不够的,还要确保实际编译各个源文件时也使用了这些选项。

确认 gcc-14.2.0 对应的 32 位目标工具链和 libgcov 可用,且最终程序确实链接了这套运行库。可以查看链接器的详细输出,并检查目标架构和库的来源,避免混用 GCC 8.5.0 与 GCC 14.2.0 的组件。

确认程序有机会写出数据

示例中的 main 返回 0,属于正常退出路径。如果真实程序通过 _exit() 退出、被强制终止、发生崩溃,或在进程退出前被系统关闭,就不能假设覆盖率数据已经写出。可以先用一份最小测试程序确认进程正常结束,再检查运行时目录和文件权限。

__gcov_dump 可以显式触发覆盖率数据写出。如果程序能正常退出,通常先验证自动写出路径即可。需要显式调用时,应使用与 GCC 14.2.0 配套的 gcov 接口声明,并在运行后检查是否生成文件。不要仅凭替换 __gcov_flush 就认定文件数量异常已经解决。

如何判断 GCC 版本兼容问题

先用 GCC 14.2.0 配套的 gcov 工具读取这次构建的 .gcno 和 .gcda,再核对目标程序实际加载或静态链接的 libgcov 是否来自相同的目标工具链。版本或目标架构混用可能导致读取或合并数据时出现问题,但现有描述不足以证明这是 .gcda 文件较少的原因。

如果递归查找确认文件确实缺失,并且已经确认所有预期目标文件都编入程序、路径正确、程序正常退出、运行目录可写,请保留完整链接命令、构建时对象文件路径、.gcno 与 .gcda 文件清单,以及程序退出方式,再比较 GCC 8.5.0 和 14.2.0 的构建产物。当前材料没有提供这些信息,无法锁定 GCC 14.2.0 的某项具体变更。

备注:内容仅供参考。