如何识别gcov中的代码块?宏展开引发的代码块定位问题
问题:宏展开导致gcov输出中单行对应多代码块的识别方案
我在解析gcov输出时,无法对应代码块与源码的关系。因为使用宏,出现了单一行对应多个代码块的情况,以下是简化示例。我的核心需求是借助标准工具实现代码块的识别,而非关注未执行内容。我可以接受查看带标记的源码、汇编或gcov列表,甚至考虑过编写程序展开宏并添加#line指令后再编译。
简化测试程序:simple.cpp
#include <stdio.h> #define F1(type, val) { printf("%s: ", #type); type i = val; while (i > 0) { if (i>10) printf("*"); printf("%ld ", (long)i--); } printf("\n"); } #define F2(type) F1(type,4) F1(type,6) int main(int , char **) { F1(int,50) F2(char) }
构建脚本:build
#!/bin/sh rm *.gc?? g++ -g -O0 --coverage -Wall -Wextra simple.cpp -o simple ./simple gcov -a simple.gc
gcov输出:simple.cpp.gcov
-: 0:Source:simple.cpp -: 0:Graph:simple.gcno -: 0:Data:simple.gcda -: 0:Runs:1 -: 1:#include <stdio.h> -: 2: -: 3:#define F1(type, val) { -: 4: printf("%s: ", #type); -: 5: type i = val; -: 6: while (i > 0) { -: 7: if (i>10) -: 8: printf("*"); -: 9: printf("%ld ", (long)i--); -: 10: } -: 11: printf("\n"); -: 12: } -: 13: -: 14:#define F2(type) F1(type,4) F1(type,6) -: 15: 1: 16:int main(int , char **) -: 17:{ 51: 18: F1(int,50) 1: 18-block 0 51: 18-block 1 50: 18-block 2 40: 18-block 3 50: 18-block 4 1: 18-block 5 11*: 19: F2(char) 5: 19-block 0 4: 19-block 1 %%%%%: 19-block 2 4: 19-block 3 1: 19-block 4 7: 19-block 5 6: 19-block 6 %%%%%: 19-block 7 6: 19-block 8 1: 19-block 9 1: 20:}
可行解决方案
1. 用gcc展开宏并保留#line指令
使用g++ -E参数展开宏,默认会保留#line指令标注原始行号。用展开后的代码编译生成gcov报告,就能把代码块关联回原始宏定义的行:
g++ -E -g simple.cpp > expanded.cpp g++ -g -O0 --coverage expanded.cpp -o simple ./simple gcov expanded.cpp
2. 结合gcov分支信息与汇编分析
编译时生成汇编代码,同时用gcov -b输出分支覆盖信息,通过汇编里的.loc调试指令,把gcov的代码块对应到原始宏行:
g++ -g -O0 --coverage -S simple.cpp -o simple.s ./simple gcov -b simple.cpp
查看simple.s中的.loc指令,每条汇编语句都会标注对应的原始源码行,以此匹配gcov中的block编号。
3. 用clang增强调试信息
clang的-fdebug-info-for-profiling参数能生成更精确的覆盖分析调试信息,编译后gcov报告可更准确地对应宏展开后的代码块到原始行:
clang++ -g -O0 --coverage -fdebug-info-for-profiling simple.cpp -o simple ./simple gcov simple.cpp
4. 手动给宏添加#line指令
手动在宏定义中插入#line指令,强制标注宏展开代码对应的原始行号,避免所有代码块集中在调用宏的行:
#define F1(type, val) \ #line 3 "simple.cpp" \ { printf("%s: ", #type); type i = val; while (i > 0) { if (i>10) printf("*"); printf("%ld ", (long)i--); } printf("\n"); } \ #line __LINE__
内容的提问来源于stack exchange,提问作者David G.
相关产品推荐
相关产品推荐

