为什么 lldb 会跳过这一行?

why does lldb skips this line?

我目前正在尝试学习 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 的第一行。

总的来说,programe 有效,但为什么 lldb 即使使用 -Onone 和 -g 也会跳转? 你能告诉我在哪里可以找到更多信息吗? 非常感谢。

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

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

为了使性能接受table 即使这是真的,swift 编译器 "unboxes" 这些类型在常见操作中并应用其他 "optimization-like" 技巧来实现所有这些走得更快。由于这是 swift 的一个普遍特征,它甚至在 -Onone 时也是如此,以使未优化代码的性能接受 table。一旦优化器开始介入,它有时会无能为力,并且会做比它在 -Onone 时应该做的更多的工作。

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

如果您知道如何阅读汇编代码,则可以查看混合反汇编以了解其实际效果。

在 lldb 中:

(lldb) dis -m -f

会给你当前框架的混合反汇编