【问题标题】:Xcode + LLDB: trying to change variable value using 'expression'Xcode + LLDB:尝试使用“表达式”更改变量值
【发布时间】:2017-03-15 13:50:01
【问题描述】:

我正在努力提高我的调试技能,因此开始阅读 here。我有以下代码:

var label = "tom"
self.label.text = label
print(label)

我在每一行中都有一个断点,我在每一行中输入

expression label = "jones"
po label

所以,当我输入po label 时,我得到了预期的结果,即jones,但标签和控制台中显示的文本(来自print(label))是tom。

我链接的教程指出更改应在程序的整个运行期间生效。是假的,还是我做错了什么?

我在 iPhone 7 Plus 模拟器上使用 Xcode 版本 8.2.1 (8C1002)。

谢谢!

【问题讨论】:

  • 我不知道关于 swift 的废话,但如果这是 objc,你正在做的事情是行不通的......在你为文本分配标签后,现在有 2 个指针指向同一个字符串,如果您更改旧标签,它不会更改 self.label.text 指向的内容...除非有一些 KVO 正在进行...po self.label.text = "jones" 做什么?
  • 当然,string 是一个结构体,我只是新建了一个 'label' 指向的结构体,而 self.label.text 仍然指向旧结构体。杰出的! :)

标签: xcode expression lldb po


【解决方案1】:

我不确定这是否有帮助,但实际情况比您想象的要复杂一些。

Swift 字符串实际上是结构,所以如果你在分配给self.text.label 之前停在行上,并为你的label var 分配一个新值,你实际上是在改变结构的内容,这应该由所有权利意味着当您从该结构分配给self.text.label 时,它确实应该获取新值...

不起作用的原因是 swift 编译器很聪明地对这些结构进行拆箱,这样它就不会在可能的情况下进行不必要的取消引用。即使在-Onone 也会发生这种情况。

因此,例如,在您的示例中,快速编译的代码已经将字符串拆箱并发出直接引用内容的代码。更改实际字符串内容不会更改对已在分配代码中的未装箱内容的引用,因此您的更改不会发生。

你可以看到这个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注释掉,那么这个改动就不再需要了。

【讨论】:

  • @Jim "如果你让编译器无法知道字符串的内容是什么,它就不能做这个拆箱,然后你会看到你的调试器更改生效。"我不确定我是否理解正确。你是说只要在运行时有一些影响struct属性的代码,比如removeSubrange,那么调试器中的更改就会生效? Int 会发生变化的例子是什么?我尝试用乘法之类的方法修改属性,但从expr 的更改仍然没有发生。
  • Ints 很简单,我对如何解决这个问题没有很好的建议。将它作为 inout 参数传递给某个函数可能会奏效。
猜你喜欢
  • 2012-04-12
  • 2020-06-25
  • 2019-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
相关资源
最近更新 更多