objective-c - 了解 gcov 文件中的分支

标签 objective-c xcode llvm gcov

我正在尝试了解 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 是什么或为什么/何时执行。

如果有人知道如何破译分支信息,或者知道有关其含义的任何详细文档,我将不胜感激。

最佳答案

Gcov 的工作原理是检测(编译时)每个基本的机器命令 block (您可以考虑汇编程序)。 Basic block表示代码的线性部分,其中没有分支,也没有标签。所以,当且仅当你开始运行一个基本 block 时,你才会到达基本 block 的末尾。基本 block 在CFG(控制流图,将其视为有向图)中组织,它显示了基本 block 之间的关系(从V1到V2的边是V1调用V2;V2被V1调用)。因此,编译器的 profile-arcs 模式和 gcov 想要获取每一行的执行计数,并通过计算基本 block 执行来实现。 CFG中的一些边被检测,一些没有,因为图中的基本 block 之间存在代数关系。

您的 ObjC 构造(for..in)被降低(在早期编译中转换)为几个基本 block 。所以,gcov 看到 4 个分支,因为它只看到降低的 BB。它对这种降低一无所知,但它知道哪一行对应于每个汇编程序指令(这是调试信息)。因此,分支是 CFG 的边。

如果您想查看基本 block ,您应该对已编译程序进行汇编程序转储,或者反汇编二进制文件或从编译器转储 CFG。您可以对 profile-arcs 和非 profile-arcs 模式执行此操作并比较它们。

profile-arcs 模式将有很多调用和增量,例如“__llvm_gcov_ctr”或“__llvm_gcda_edge”——它是基本 block 的实际检测。

关于objective-c - 了解 gcov 文件中的分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7060005/

相关文章:

swift - 不受支持的 swift 版本 (SWIFT 5)

ios - 使 Core Data 中 API 的本地缓存数据失效

ios - 具有固定宽度和 1 行的 UILabel,内容有时与省略号的训练不完全一致

XCode 4.3 字体和颜色导出

objective-c - 什么是 Xcode 中的异常断点

llvm - 结合使用LLVM opt和内置 channel

c - 为什么 GCC/Clang 在不同情况下的初始化行为不同?

gdb - 在 LLDB 中将反汇编风格设置为 Intel

ios - 点击按钮时更改 UIBarButtonItem tintColor?

ios - 在 UIButton 之间滑动