Xcode + LLDB:尝试使用 'expression' 更改变量值
Xcode + LLDB: trying to change variable value using 'expression'
我正在努力提高我的调试技能,所以开始阅读 here。我有以下代码:
var label = "tom"
self.label.text = label
print(label)
我在每一行中都有一个断点,我在每一行中输入
expression label = "jones"
po label
因此,当我键入 po label
时,我得到了预期的结果,即 jones
,但标签和控制台(来自 print(label)
)中显示的文本是 tom
.
我链接的教程指出更改应该对整个 运行 程序生效。这是假的,还是我做错了什么?
我正在使用 Xcode 版本 8.2.1 (8C1002) 和 iPhone 7 Plus 模拟器。
谢谢!
我不确定这是否有帮助,但实际情况比您想象的要复杂一些。
Swift 字符串实际上是结构,因此如果您在分配给 self.text.label
之前停在行上并为 label
var 分配一个新值,您实际上是在改变结构的内容,这应该意味着当您从该结构分配给 self.text.label
时,它确实应该获取新值...
不起作用的原因是 swift 编译器很聪明地拆箱这些结构,因此它不会在可能的情况下进行不必要的取消引用。即使在 -Onone
.
也会发生这种情况
因此,例如,在您的示例中,swift 编译代码已经对字符串进行拆箱并发出直接引用内容的代码。更改实际的字符串内容不会更改对赋值代码中已拆箱内容的引用,因此您的更改不会生效。
你可以看到这个IRL:如果你让编译器不知道字符串的内容是什么,它就不能做这个拆箱,然后你会看到你的调试器更改生效。
使用此示例代码:
class HasLabel
{
var label : String = "Default Value"
}
func
main ()
{
var myLabel = HasLabel()
var string = "set in code"
string.removeSubrange(string.startIndex..<string.endIndex)
string.append("Different string in code")
myLabel.label = string // Set a breakpoint here
print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
}
main()
在调试器中,我看到:
(lldb) br s -p "Set a breakpoint here"
Breakpoint 1: where = tryme`tryme.main () -> () + 499 at tryme.swift:14, address = 0x0000000100001e93
(lldb) run
Process 8323 launched: '/private/tmp/tryme' (x86_64)
Process 8323 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100001e93 tryme`tryme.main () -> () at tryme.swift:14
11
12 string.removeSubrange(string.startIndex..<string.endIndex)
13 string.append("Different string in code")
-> 14 myLabel.label = string // Set a breakpoint here
^
15 print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
16 }
17
(lldb) expr string = "Set in debugger"
(lldb) c
Process 8323 resuming
Did it change? string: "Set in debugger" Label: "Set in debugger"
Process 8323 exited with status = 0 (0x00000000)
您可以看到实际发生的调试器更改。但是如果你注释掉string.removeSubrange
和string.append
,那么改变就不再需要了。
我正在努力提高我的调试技能,所以开始阅读 here。我有以下代码:
var label = "tom"
self.label.text = label
print(label)
我在每一行中都有一个断点,我在每一行中输入
expression label = "jones"
po label
因此,当我键入 po label
时,我得到了预期的结果,即 jones
,但标签和控制台(来自 print(label)
)中显示的文本是 tom
.
我链接的教程指出更改应该对整个 运行 程序生效。这是假的,还是我做错了什么?
我正在使用 Xcode 版本 8.2.1 (8C1002) 和 iPhone 7 Plus 模拟器。
谢谢!
我不确定这是否有帮助,但实际情况比您想象的要复杂一些。
Swift 字符串实际上是结构,因此如果您在分配给 self.text.label
之前停在行上并为 label
var 分配一个新值,您实际上是在改变结构的内容,这应该意味着当您从该结构分配给 self.text.label
时,它确实应该获取新值...
不起作用的原因是 swift 编译器很聪明地拆箱这些结构,因此它不会在可能的情况下进行不必要的取消引用。即使在 -Onone
.
因此,例如,在您的示例中,swift 编译代码已经对字符串进行拆箱并发出直接引用内容的代码。更改实际的字符串内容不会更改对赋值代码中已拆箱内容的引用,因此您的更改不会生效。
你可以看到这个IRL:如果你让编译器不知道字符串的内容是什么,它就不能做这个拆箱,然后你会看到你的调试器更改生效。
使用此示例代码:
class HasLabel
{
var label : String = "Default Value"
}
func
main ()
{
var myLabel = HasLabel()
var string = "set in code"
string.removeSubrange(string.startIndex..<string.endIndex)
string.append("Different string in code")
myLabel.label = string // Set a breakpoint here
print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
}
main()
在调试器中,我看到:
(lldb) br s -p "Set a breakpoint here"
Breakpoint 1: where = tryme`tryme.main () -> () + 499 at tryme.swift:14, address = 0x0000000100001e93
(lldb) run
Process 8323 launched: '/private/tmp/tryme' (x86_64)
Process 8323 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100001e93 tryme`tryme.main () -> () at tryme.swift:14
11
12 string.removeSubrange(string.startIndex..<string.endIndex)
13 string.append("Different string in code")
-> 14 myLabel.label = string // Set a breakpoint here
^
15 print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"")
16 }
17
(lldb) expr string = "Set in debugger"
(lldb) c
Process 8323 resuming
Did it change? string: "Set in debugger" Label: "Set in debugger"
Process 8323 exited with status = 0 (0x00000000)
您可以看到实际发生的调试器更改。但是如果你注释掉string.removeSubrange
和string.append
,那么改变就不再需要了。