【问题标题】:why does lldb skips this line?为什么 lldb 跳过这一行?
【发布时间】:2017-08-07 07:09:28
【问题描述】:

我目前正在尝试学习 swift,在编写一些虚拟代码时,我注意到 xcode 跳过了一些行,有时会停在奇怪的行上。我的环境:macos sierra,xcode 版本 8.2.1 (8C1002)

由于xcode跳过了一些行,我认为问题出在代码优化上,然后我切换到终端调试,下面是输入和输出

我用

编译
swiftc -g -Onone *.swift

然后

用 lldb 加载它

lldb main

如下所示在 lint 18 上设置断点并使用“r”运行进程

   17   do {
-> 18       try StaticM.teststatic2()
   19       print (1)
   20   }catch {
   21       
(lldb) thread step-in
Process 963 stopped
* thread #1: tid = 0x86e1, 0x0000000100001f6a main`static StaticM.teststatic2(self=main.StaticM, $error=Error @ 0x00007fff5fbffac0) throws -> () + 26 at staticExt.swift:13, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100001f6a main`static StaticM.teststatic2(self=main.StaticM, $error=Error @ 0x00007fff5fbffac0) throws -> () + 26 at staticExt.swift:13
   10   public extension StaticM {
   11       @discardableResult
   12       public static func teststatic2() throws  {
-> 13           var asdf=2;
   14           let sdfgsdfg=2;
   15           print(sdfgsdfg);
   16           print (asdf);
(lldb) n
Process 963 stopped
* thread #1: tid = 0x86e1, 0x0000000100001f72 main`static StaticM.teststatic2(self=main.StaticM, $error=Error @ 0x00007fff5fbffac0) throws -> () + 34 at staticExt.swift:15, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100001f72 main`static StaticM.teststatic2(self=main.StaticM, $error=Error @ 0x00007fff5fbffac0) throws -> () + 34 at staticExt.swift:15
   12       public static func teststatic2() throws  {
   13           var asdf=2;
   14           let sdfgsdfg=2;
-> 15           print(sdfgsdfg);
   16           print (asdf);
   17           asdf += 1;
   18       }
(lldb) process continue
Process 963 resuming
2
2
1
Process 963 exited with status = 0 (0x00000000) 
(lldb)  

问题是,我在 lldb 中使用“n”进入下一行后,为什么 lldb 会跳过 staticExt.swift 的第 14 行并直接跳到第 15 行?

另外,有时在尝试调试其他程序时,我在 xcode 中单击“step-in”,它停在 func 的声明行而不是代码块中的第一行,我单击 stepover,它返回到调用者 func 行,而不是执行该 func 的第一行。

总而言之,程序可以工作,但为什么 lldb 即使使用 -Onone 和 -g 也会跳转? 你能告诉我在哪里可以找到更多信息吗? 非常感谢。

【问题讨论】:

    标签: swift xcode llvm lldb


    【解决方案1】:

    Swift 的基本类型(Int's、Strings 等)在形式上有些重量级 - 例如在您的示例中:

    (lldb) expr --raw -- asdf
    (Swift.Int) $R0 = {
      _value = 3
    }
    

    即使这是真的,为了使性能可以接受,swift 编译器在常见操作中“取消装箱”这些类型,并应用其他“类似优化”的技巧来使这一切变得更快。由于这是 swift 的一个普遍特性,它甚至在 -Onone 下也是如此,以使未优化代码的性能可以接受。并且一旦优化器开始参与其中,它有时会无法自救,并且会做比在 -Onone 上应该做的更多的工作。

    在这种情况下,因为第一个变量是一个 Int 的“let”,swiftc 知道它可以在调用 print 时直接将值插入到参数中,所以它不需要组成一个变量.如果您将let 更改为var,则实际上将为该行生成代码,并且该行将获得自己的行表条目。

    如果您知道如何阅读汇编代码,则可以查看混合反汇编以了解这一点。

    在 lldb 中:

    (lldb) dis -m -f
    

    会给你当前帧的混合反汇编。

    【讨论】:

    • 谢谢 Jim。这真的很有帮助。我可以假设 swiftc 还在做其他一些技巧,因为我遇到了一些其他奇怪的事情,比如它不会在 func 块的第一行停止,而是在func 声明行?我在哪里可以找到 swiftc 的功能?谢谢
    • 这似乎很有可能。没有一个地方可以描述优化器在 -Onone 的行为,而且“优化器”也不是一个实体,它是一堆单独的通道,每个通道都试图完成自己的工作。您可以使用 lldb 命令image dump line-table MySource.swift 查看调试信息中存在的“行表”,但这只会告诉您调试器有哪些信息,而不是为什么 swift 编译器决定以这种方式构建它。
    猜你喜欢
    • 1970-01-01
    • 2013-02-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 2017-02-01
    • 1970-01-01
    相关资源
    最近更新 更多