为什么变异成员不触发 Xcode 中的断点?
Why aren't mutating members triggering breakpoints in Xcode?
我遇到了一些我无法从阅读 Xcode 或 LLDB 的文档中弄清楚的事情。当应用程序到达具有断点的行时,在我看来,如果存在断点,LLDB 应该在该行上中断。如果在执行变异函数时访问该行的代码将不会触发断点。
考虑以下示例:
class DataSource {
private init(){
data = []
for i in 0..<10 {
data.append(i) // mutating func
}
}
static let sharedInstance = DataSource()
var data: [Int]! // Set a breakpoint on this line
}
class Worker {
func work(){
print("Append item")
DataSource.sharedInstance.data.append(23) // mutating func
print("Get first item")
print(DataSource.sharedInstance.data[0]) // subscript - TRIGGERS BREAKPOINT
print("Drop first")
print(DataSource.sharedInstance.data.dropFirst()) // func - TRIGGERS BREAKPOINT
print("Remove first")
print(DataSource.sharedInstance.data.removeFirst()) // mutating func
print("Remove at 0")
print(DataSource.sharedInstance.data.remove(at: 0)) // mutating func
}
}
.data[0]
和 .dropFirst()
正在触发断点,其他函数调用不是。我能看到的唯一区别是那些没有破坏的功能是 mutating
功能。
不触发断点,每次在同一行添加观察点都会触发
有人可以解释一下这种行为吗?
在 macOS 上,您的断点解析为:
(lldb) break list
Current breakpoints:
1: source regex = "Set a breakpoint", exact_match = 0, locations = 3, resolved = 3, hit count = 3
1.1: where = mutable`mutable.DataSource.(in _788A7EC739C0395377AC3966BEDD9D35).init() -> mutable.DataSource + 40 at mutable.swift:15, address = 0x0000000100001b08, resolved, hit count = 1
1.2: where = mutable`mutable.DataSource.data.getter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 80 at mutable.swift:15, address = 0x0000000100001e00, resolved, hit count = 2
1.3: where = mutable`mutable.DataSource.data.setter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 96 at mutable.swift:15, address = 0x0000000100001e70, resolved, hit count = 0
这是有道理的,"data" ivar 的定义产生了 setter、getter 和 init 方法,这些函数与此行相关联。
但是如果您查看可变访问的代码,例如追加调用,使用了这些方法的 none,程序集看起来像:
(lldb) dis -c 5 -s 0x10000203b
mutable`Worker.work():
0x10000203b <+235>: callq 0x100002cf0 ; type metadata accessor for mutable.DataSource at mutable.swift
0x100002040 <+240>: movq %rax, -0xf0(%rbp)
0x100002047 <+247>: callq 0x100001d50 ; mutable.DataSource.sharedInstance.unsafeMutableAddressor : mutable.DataSource at mutable.swift
0x10000204c <+252>: movq (%rax), %rax
0x10000204f <+255>: movq %rax, %rcx
它正在通过类型元数据来访问它要更改的变量。这是一个通用函数,不会由 "data" ivar 的定义触发,因此它不会分配给该定义行。该访问必须知道它可以跳过 getter 或 setter,但您必须让其他人解释为什么这样做...
如果您对此感到好奇,您可以尝试将您的问题改写为关于 Swift 为数据访问所做的选择,并且更熟悉该语言实现的人可能会参与进来。
我遇到了一些我无法从阅读 Xcode 或 LLDB 的文档中弄清楚的事情。当应用程序到达具有断点的行时,在我看来,如果存在断点,LLDB 应该在该行上中断。如果在执行变异函数时访问该行的代码将不会触发断点。
考虑以下示例:
class DataSource {
private init(){
data = []
for i in 0..<10 {
data.append(i) // mutating func
}
}
static let sharedInstance = DataSource()
var data: [Int]! // Set a breakpoint on this line
}
class Worker {
func work(){
print("Append item")
DataSource.sharedInstance.data.append(23) // mutating func
print("Get first item")
print(DataSource.sharedInstance.data[0]) // subscript - TRIGGERS BREAKPOINT
print("Drop first")
print(DataSource.sharedInstance.data.dropFirst()) // func - TRIGGERS BREAKPOINT
print("Remove first")
print(DataSource.sharedInstance.data.removeFirst()) // mutating func
print("Remove at 0")
print(DataSource.sharedInstance.data.remove(at: 0)) // mutating func
}
}
.data[0]
和 .dropFirst()
正在触发断点,其他函数调用不是。我能看到的唯一区别是那些没有破坏的功能是 mutating
功能。
不触发断点,每次在同一行添加观察点都会触发
有人可以解释一下这种行为吗?
在 macOS 上,您的断点解析为:
(lldb) break list
Current breakpoints:
1: source regex = "Set a breakpoint", exact_match = 0, locations = 3, resolved = 3, hit count = 3
1.1: where = mutable`mutable.DataSource.(in _788A7EC739C0395377AC3966BEDD9D35).init() -> mutable.DataSource + 40 at mutable.swift:15, address = 0x0000000100001b08, resolved, hit count = 1
1.2: where = mutable`mutable.DataSource.data.getter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 80 at mutable.swift:15, address = 0x0000000100001e00, resolved, hit count = 2
1.3: where = mutable`mutable.DataSource.data.setter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 96 at mutable.swift:15, address = 0x0000000100001e70, resolved, hit count = 0
这是有道理的,"data" ivar 的定义产生了 setter、getter 和 init 方法,这些函数与此行相关联。
但是如果您查看可变访问的代码,例如追加调用,使用了这些方法的 none,程序集看起来像:
(lldb) dis -c 5 -s 0x10000203b
mutable`Worker.work():
0x10000203b <+235>: callq 0x100002cf0 ; type metadata accessor for mutable.DataSource at mutable.swift
0x100002040 <+240>: movq %rax, -0xf0(%rbp)
0x100002047 <+247>: callq 0x100001d50 ; mutable.DataSource.sharedInstance.unsafeMutableAddressor : mutable.DataSource at mutable.swift
0x10000204c <+252>: movq (%rax), %rax
0x10000204f <+255>: movq %rax, %rcx
它正在通过类型元数据来访问它要更改的变量。这是一个通用函数,不会由 "data" ivar 的定义触发,因此它不会分配给该定义行。该访问必须知道它可以跳过 getter 或 setter,但您必须让其他人解释为什么这样做...
如果您对此感到好奇,您可以尝试将您的问题改写为关于 Swift 为数据访问所做的选择,并且更熟悉该语言实现的人可能会参与进来。