我目前正在尝试学习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? 你能告诉我在哪里可以找到更多信息吗? 非常感谢你。
答案 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
将为您提供当前帧的混合反汇编。