为什么lldb会跳过这一行?

时间:2017-03-16 08:11:59

标签: swift xcode llvm lldb

我目前正在尝试学习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)  

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

另外,有时在尝试调试其他程序时,我点击"步入"在xcode中,它停止在func的声明行而不是代码块中的第一行,我单击了stepover,它返回到调用者函数行,而不是执行该函数的第一行。

总之,programe工作,但为什么lldb甚至跳 - -Onone和-g? 你能告诉我在哪里可以找到更多信息吗? 非常感谢你。

1 个答案:

答案 0 :(得分:1)

Swift的基本类型(Int' s,Strings等)在形式上有点重量级 - 例如在你的例子中:

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

为了使性能可以接受,即使这是真的,swift编译器" unboxes"这些类型在常见操作中并适用于其他类似优化的"让所有这些变得更快的技巧。由于这是swift的一个普遍特征,所以即使在-Onone也可以这样做,以使未经优化的代码的性能可以接受。一旦优化器开始参与其中,它有时无法帮助自己,并且会做更多的工作,而不是应该在-Onone。

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

如果您知道如何阅读汇编代码,则可以查看混合反汇编以查看此操作。

在lldb:

(lldb) dis -m -f

将为您提供当前帧的混合反汇编。