我正在尝试了解gcov工具的输出。没有选项运行它是有道理的,但我想尝试理解分支覆盖选项。不幸的是,很难理解分支机构的作用以及为什么不采用它们。下面是方法的输出(使用最新的LLVM / Clang构建进行编译)。
function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88%
5: 30:- (NSInteger)loopThroughArray:(NSArray *)array {
5: 31: NSInteger i = 0;
22: 32: for (NSString *string in array) {
branch 0 taken 0
branch 1 taken 7
-: 33:
22: 34: }
branch 0 taken 4
branch 1 taken 3
branch 2 taken 0
branch 3 taken 3
5: 35: return i;
-: 36:}
我通过这个运行5次测试,传入nil,一个空数组,一个包含1个对象的数组,包含2个对象的数组和一个包含4个对象的数组。我可以猜测,在第一种情况下,分支1意味着“进入循环”,但我不知道分支0是什么。在第二种情况下,分支0似乎再次循环,分支1似乎结束循环,分支3继续/退出循环,但我不知道分支2是什么或为什么/何时执行。< / p>
如果有人知道如何破译分支信息,或者知道有关这一切的详细文档,我会很感激帮助。
答案 0 :(得分:3)
Gcov通过仪器化(编译时)每个基本的机器命令块(你可以考虑汇编程序)来工作。 Basic block表示代码的线性部分,其中没有分支,内部没有标记。因此,当且仅当您开始运行基本块时,您将到达基本块的末尾。基本块在CFG中组织(控制流程图,将其视为有向图),其显示基本块之间的关系(V1到V2的边缘是V1调用V2; V2调用V1)。因此,编译器和gcov的profile-arcs
模式希望获得每一行的执行计数,并通过计算基本块执行来完成此操作。 CFG中的一些边缘是有装备的,有些则不是,因为图形中的基本块之间存在代数关系。
您的ObjC构造(for..in)被降低(在早期编译中转换)到几个基本块。因此,gcov看到4个分支,因为它只看到降低的BBs。它对此降低一无所知,但它知道哪条线对应于每个汇编指令(这是调试信息)。因此,分支是CFG的边缘。
如果要查看基本块,则应该对已编译的程序进行汇编程序转储,或者从编译器中反汇编二进制文件或转储CFG。您可以对profile-arcs
和非profile-arcs
模式执行此操作并进行比较。
profile-arcs
模式将有很多调用和增量,例如“__llvm_gcov_ctr”或“__llvm_gcda_edge” - 它是基本块的实际工具。