如何防止未使用函数被链接器/编译器剔除以准确统计代码覆盖率?
解决GCC/gcov统计库覆盖率时未使用函数被链接器剔除的问题
在Linux环境下用GCC和gcov统计库L的代码覆盖率时,未被测试用例引用的L::foo()会被链接器默认剔除,导致覆盖率统计虚高。以下是几种可行的解决方法:
方法一:强制链接整个库
通过链接器选项--whole-archive强制链接库的所有目标文件,即使其中的函数未被引用。修改链接命令时需注意,该选项仅作用于紧跟其后的库,之后要用--no-whole-archive恢复默认行为,避免影响其他库:
gcc test.o -Wl,--whole-archive -lL -Wl,--no-whole-archive -o test
-Wl,xxx:将xxx参数传递给链接器ld--whole-archive:链接指定库的所有目标文件,不剔除未引用符号--no-whole-archive:恢复链接器默认的只链接引用符号的行为
方法二:标记单个函数为必须保留
如果只想保留特定未使用的函数(比如L::foo()),可以在函数的声明或定义中添加__attribute__((used))属性,告诉编译器和链接器该函数必须保留:
// 函数声明时添加 void L::foo() __attribute__((used)); // 或者函数定义时添加 void L::foo() __attribute__((used)) { // 函数实现 }
这个方法适合只需要保留少量未使用函数的场景,不会引入整个库的冗余代码。
方法三:调整符号可见性设置
如果库编译时使用了-fvisibility=hidden(默认隐藏非导出符号),链接器会更积极地剔除未引用的隐藏符号。此时可以:
- 给需要保留的函数添加可见性属性:
void L::foo() __attribute__((used, visibility("default")));
- 或者暂时移除
-fvisibility=hidden编译选项(如果不影响库的正常使用)
关键注意事项
- 编译库L时必须添加
-fprofile-arcs -ftest-coverage选项,生成gcov所需的.gcno覆盖信息文件:
gcc -c -fprofile-arcs -ftest-coverage libL.cpp -o libL.o ar rcs libL.a libL.o
- 测试程序编译链接时也需要带上上述覆盖率选项,确保能生成
.gcda执行数据文件 - 验证函数是否被保留:可以用
nm命令检查测试程序的符号表,确认L::foo()存在:
nm test | grep "L::foo"
完成上述设置后,运行测试用例生成.gcda文件,再用gcov或lcov工具统计覆盖率,就能看到L::foo()显示为未覆盖状态,统计结果更准确。
内容的提问来源于stack exchange,提问作者dwto
相关产品推荐
相关产品推荐

